Trang chủ Lập trình C# LinQ Performance - "multiple enumerations" khi sử dụng IEnumerable
Lập trình C# 21/06/2020 5,759 lượt xem

LinQ Performance - "multiple enumerations" khi sử dụng IEnumerable

LinQ Performance - "multiple enumerations" khi sử dụng IEnumerable

Trong các dự án thực tế, khi viết các phương thức dùng chung cho các yêu cầu khác nhau, với các phương thức liên quan đến tập hợp (array, collection, list), các lập trình viên thường sử dụng IEnumerable<T>. Phương thức này cơ bản có dạng như sau:
 

public IEnumerable<T> GetTObjects()
{
    //do something
    //IEnumerable<T> result = ....;
    //return result;
}

Sau đó, ở các phương thức khác chỉ cần gọi phương thức GetTObjects() và tiếp tục xử lý tập hợp. Với tập hợp này, do yêu cầu nghiệp vụ, chúng ta phải xử lý 1 chuỗi câu lệnh như kiểm tra tập hợp rỗng, tìm các phần tử thỏa mãn 1 điều kiện nào đó, loại bỏ bớt phần tử theo điều kiện nào đó... Và trong rất nhiều trường hợp như thế này, chúng ta thường hay gặp cách viết mã chương trình theo dạng như sau:

 

public void ProcessTObjects(){
  
  var objects = GetTObjects();

  if(!objects.Any()){
     //do something
  }

  var object = objects.FirstOrDefault(Func<T, bool> samplePredicate);

  if(object != null) {
     //do something
  }

  var otherObjects = objects.Where(Func<T, bool> samplePredicate);
  
  foreach(var obj in otherObjects){
     
     //do something 
  }
  
  //more code ...
}

Cách viết này theo nghiệp vụ là ok và đúng logic rồi. Tuy nhiên, dạng code theo cách như trên sẽ gây ra 'Multiple Enumerations', hiểu 1 cách đơn giản là IEnumerable<T> được evaluate lại nhiều lần và như vậy sẽ làm giảm performance của chương trình. Trong đoạn mã dạng trên, sẽ có ít nhất 3 lần IEnumerable<T> được evaluate:

- Lần 1 là dòng code sử dụng phương thức Any().
- Lần 2 là dòng code sử dụng phương thức FirstOrDefault().
- Lần 3 là dòng code sử dụng phương thức Where().

Để tránh điều này xảy ra, chúng ta phải làm cho IEnumerable<T> được evaluate 1 lần duy nhất trong phương thức trên. Để thực hiện điều này, chúng ta nên cast IEnumerable<T> sang dạng List<T> hoặc Array<T> ngay tại thời điểm lấy về IEnumerable<T>. Cụ thể ở đây, chúng ta sửa như sau:
 

Chuyển: 'var objects = GetTObjects()' thành 'var objects = GetTObjects().ToList()' hoặc  'var objects = GetTObjects().ToArray()'


Với cách xử lý này, ở các đoạn code tiếp theo, chúng ta sẽ làm việc với List<T> hoặc Array<T>, chứ không còn phải làm việc với IEnumerable<T> nữa, và đảm bảo được IEnumerable<T> chỉ được evaluate 1 lần duy nhất.

Các bạn có thể chuyển đoạn code sang 1 chương trình cụ thể và test thử để xem hiệu quả. Ngoài ra, để nắm vững các kiến thức về LINQ cũng như tránh được các lỗi trong LINQ theo dạng code như trong bài viết đã đề cập, các bạn nên tìm hiểu Deffered Execution và Immediate Execution trong linQ hoặc có thể tham dự khóa học về LINQ của trang tedu.

Tác giả: Nguyễn Thanh Sơn

Chú ý: Tất cả các bài viết trên TEDU.COM.VN đều thuộc bản quyền TEDU, yêu cầu dẫn nguồn khi trích lại trên website khác.

Chia sẻ:

Bài viết liên quan

Tìm hiểu về các loại Collection trong C#
11/12/2024 Bạch Ngọc Toàn

Tìm hiểu về các loại Collection trong C#

Trong C#, collections là các cấu trúc dữ liệu được sử dụng để lưu trữ và quản lý các nhóm đối tượng. C# cung cấp nhiều loại collections khác nhau để phù hợp với các yêu cầu cụ thể của lập trình viên

Đọc thêm
Sử dụng mảng (Arrays)
11/12/2024 Bạch Ngọc Toàn

Sử dụng mảng (Arrays)

Mảng trong C# là một cấu trúc dữ liệu lưu trữ một dãy các phần tử có bộ nhớ nằm liên tiếp nhau và có kích thước cố đinh.

Đọc thêm
Lập trình hướng đối tượng
11/12/2024 Bạch Ngọc Toàn

Lập trình hướng đối tượng

Lập trình hướng đối tượng (Object Oriented Programing) hay còn gọi là OOP. Là một kỹ thuật lập trình cho phép các lập trình viên có thể ánh xạ các thực thể bên ngoài đời thực và trừu tượng hoá thành các class và object trong mã nguồn.

Đọc thêm
Vòng lặp (loop)
11/12/2024 Bạch Ngọc Toàn

Vòng lặp (loop)

Trong thực tế khi bạn cần thực thi một khối lệnh nhiều lần. Vòng lặp cho phép chúng ta thực thi một câu lệnh hoặc một khối lệnh nhiều lần.

Đọc thêm