Ienumerable c# là gì

     
*

The Programmable Me


Ở phần 1, họ đã bàn về Functional programing (FP). Giả dụ như đấy là lần đầu chúng ta tiếp xúc với quan niệm này và cảm xúc nó khó hiểu thì cũng đừng sợ, vì người nào cũng giống chúng ta cả thôi. FP là một khái niệm quan trọng đặc biệt và cũng là trong những cơ sở nhằm Linq trong .NET được xây dựng. Vị vậy trong quá trình tò mò về Linq, bạn cũng trở thành hiểu rõ được hơn về FP.

Bạn đang xem: Ienumerable c# là gì

Trở lại với Linq, công dụng của C# cung ứng bạn thao tác làm việc với những tập đúng theo dữ liệu. Trong số những điều cơ mà mình thấy những lập trình viên mắc phải, đó là việc sử dụng Linq không đúng quy bí quyết do thiếu hiểu biết nhiều rõ thực chất của tủ sách này. Họ hãy thử quan sát vào khái niệm của một method Linq điển dường như Where():

public static IEnumerable Where(this IEnumerable source,Func predicate)Như chúng ta thấy, method này được viết dưới dạng “extionsion method”. Đối với phần đông ai ko biết, “extension method” là 1 trong những tính năng của C# nhằm mục đích giúp không ngừng mở rộng thêm những method cho class hoặc interface của người tiêu dùng bằng câu hỏi viết nó bên dưới dạng “static” ở 1 class không giống và sử dụng từ khóa “this”. Ở method trên, bạn có thể thấy rằng, interface được mở rộng là IEnumerable. Nếu như bạn đã hiểu kĩ phần trước, các bạn sẽ biết rằng IEnumerable là interface đa số được Linq phía đến.Vì vậy để hiểu rõ Linq thì chúng ta cần nắm vững về interface này.

IEnumerable cùng từ khóa yield return

IEnumerable được định nghĩa trong System.Collection.Generics và là một trong interface vô cùng solo giản:

public interface IEnumerable IEnumerator GetEnumerator();Như chúng ta thấy, interface này chỉ có một method duy nhất, GetEnumerator(), trả về một giá trị bao gồm dạng IEnumerator. IEnumerator được quan niệm như sau:

public interface IEnumerator T Currentget; void Dispose(); bool MoveNext(); void Reset();Nhìn vào hai interface trên, vững chắc hẳn các bạn cũng đoán được chân thành và ý nghĩa của chúng. IEnumerator chất nhận được bạn triển khai đọc qua tất cả các giá trị trong một tập hợp. Hãy tưởng tượng ai đang muốn đọc cùng xử lý những dòng vào một bảng biểu, khi bạn có nhu cầu đọc sang dữ liệu tiếp theo, các bạn gọi MoveNext() cùng đọc tài liệu đó qua trực thuộc tính Current. Khi không còn dữ liệu nữa, MoveNext() vẫn trả về false. Chúng ta có thể đọc lại từ đầu bằng method Reset(), hoặc xóa bỏ cả tập hợp bằng Dispose()

IEnumerable là interface cơ bản nhất thay mặt cho những kiểu tập hợp tài liệu trong C#, vị nó tư tưởng những tuấn kiệt cơ bạn dạng nhất mà lại một tập hợp nên có: tài năng đọc các thành phần một cách lần lượt. Toàn bộ các class dùng làm chứa những tập hợp tài liệu (Dictionary, Collection, ArrayList, List…) đều kế thừa từ interface này. IEnumerable cũng chính là interface được cho phép bạn call từ khóa foreach , về cơ bạn dạng chính là một vòng lặp mà tự động gọi MoveNext() và Current

Việc triển khai interface này khá solo giản: bạn cũng có thể viết một linked-list để cất dữ liệu, do linked-list cũng được cho phép truy cập phần tử một cách lần lượt như vậy. Tuy nhiên trong C#, họ có một phương pháp viết khác để tự động hóa xây dựng một kết cấu dữ liệu loại IEnumerable, chính là việc áp dụng từ khóa yield return.

Cách tốt nhất có thể để đọc được từ bỏ khóa này là dùng ví dụ:

IEnumerable generateString() yield return "one"; yield return "two"; yield return "three";Hàm generateString() ko gọi bất kể class nào thừa kế từ IEnumerable cả, mà cần sử dụng từ khóa yield return. Khi 1 hàm thực hiện từ khóa này, hàm này được gọi là “Generator”. Khi hàm này chạm chán từ khóa “yield return“, nó sẽ hoàn thành hoạt rượu cồn và đưa giá trị được yield đó vào chuỗi IEnumerable nhưng nó trả về. Bây giờ tại hàm gọi Generator đó, bạn cũng có thể đọc được ngay giá chỉ trị thứ nhất đó. Khi bạn có nhu cầu đọc giá trị tiếp theo(bằng giải pháp dùng foreach hoặc call MoveNext()), Generator sẽ tiếp tục chạy từ địa chỉ yield return cũ cho đến từ khóa yield return tiếp theo. Những lần hotline giá trị sau cũng diễn ra y giống hệt như vậy. Đến lúc hàm này không gặp từ khóa yield return nào nữa(hoặc lúc nó chạm chán từ khóa yield break) thì chuỗi IEnumerable trả về sẽ được hoàn vớ (đây là lúc mà lại MoveNext() trả về false)

Để dễ hiểu hơn, hãy xem thêm ví dụ sau đây.

Xem thêm: Giá Iphone 5 Tại Việt Nam : Iphone 5 Có Giá Khởi Điểm 15 Triệu Đồng

private static IEnumerable generateStrings() Console.WriteLine("yield one"); yield return "one"; Console.WriteLine("yield two"); yield return "two"; Console.WriteLine("yield three"); yield return "three";//codevar seq = generateStrings();foreach(string s in seq) Console.WriteLine($"loop i++"); Console.WriteLine(s);//output//yield one//loop 1//one//yield two//loop 2//two//yield three//loop 3//threeBạn hoàn toàn có thể thấy là hàm generateStrings() chỉ thường xuyên chạy khi vòng lặp foreach chuyển sang giá trị tiếp theo sau của chuỗi IEnumerable. Đây là vấn đề làm bắt buộc điểm hay độc nhất vô nhị của IEnumerable: lazy evaluation, có nghĩa là chỉ thực hiện giám sát và trả về tài liệu khi được gọi. Ứng dụng của nhân kiệt này là khôn cùng lớn: Hãy tưởng tượng các bạn đang thao tác làm việc với một nguồn dữ liệu khổng lồ, được gọi xuất phát điểm từ 1 nguồn dữ liệu nào đó (database, network…). Bạn không thích gọi tất cả các tài liệu đó cùng lúc, bởi nó quá to và quá mất thời gian, mà cố gắng vào đó là điện thoại tư vấn chúng một cách lần lượt. Khi bạn không muốn liên tục gọi dữ liệu nữa, chúng ta có thể ngừng Generator này lại bằng những gọi yield break ở bên phía trong hàm generator, hoặc điện thoại tư vấn Dispose() sống IEnumerator của IEnumerable mà bạn nhận được. Dạng hình như sau:

IEnumerable getRecords() int i=0; while(true) Record record = ReadRecord(i++); yield return record; void Process() var records = getRecords(); var enumerator = records.GetEnumerator(); while(enumerator.MoveNext()) ProcessResult result = ProcessRecord(enumerator.Current); if (result == ProcessResult.Enough) enumerator.Dispose(); return; Nếu bạn thấy những điều trên là rất khó hiểu thì cũng không có gì đáng lo âu cả, vày generator là một khái niệm tương đối khó vắt bắt. Cách rất tốt để phát âm được nó là hãy mở Visual Studio lên với bỏ thời gian nghịch ngợm một chút.

Hàm Where vào Linq

Giờ thì chắc các bạn cũng nắm bắt được kha khá về IEnumerable rồi (nếu như không thì lời khuyên của bản thân mình là nên ngừng đọc với dành chút thời gian để test nghiệm). Họ hãy thử dùng điều này để viết lại một hàm dễ dàng và đơn giản nhất trong Linq: Where (xem định nghĩa hàm này nghỉ ngơi đầu bài)

Hàm Where về cơ phiên bản có công dụng giống như 1 filter(tương trường đoản cú như câu “WHERE” trong sql). Nó giúp đỡ bạn chọn thanh lọc ra những bộ phận trong một tập thích hợp mà thỏa mãn nhu cầu một yêu cầu nào đó. Chúng ta hãy trở về ví dụ với hàm generateStrings() đang viết sống trên(đã thải trừ các đoạn Console.WriteLine()). Trả sử bạn muốn chọn thanh lọc ra rất nhiều string tất cả độ dài nhỏ dại hơn 4 (trong trường vừa lòng trên là “one” và “two”). Chúng ta hoàn toàn có thể viết như sau

public static class MyLinq{ public static IEnumerable Where(this IEnumerable source) { foreach(string s in source) { if(s.LengthĐiều này có nghĩa rằng chỉ hồ hết đoạn cực hiếm string nào tất cả độ dài nhỏ tuổi hơn 4 bắt đầu được hàm này tiếp nhận và đưa vào giá trị IEnumerable đầu ra.

Xem thêm: Mã Lệnh Đang Được Cpu Thực Hiện Lưu Trữ Ở Đâu, Quá Trình Xử Lý Thông Tin

Đoạn code trên vận động hoàn toàn đúng, ngoại trừ trừ việc nó không có tính tái sử dụng cho lắm: các bạn không tinh chỉnh được ngắn gọn xúc tích lựa chọn của hàm Where, và hàm Where lúc này chỉ hoạt động với mẫu mã string mà thôi. Các bạn có đừng quên trong phần trước, họ có kể tới việc C# cung ứng kiểu tài liệu Func. Bọn họ hãy viết lại hàm Where nhằm tận dụng điều này:

public static class MyLinq public static IEnumerable Where(this IEnumerable source, Func predicate) foreach(T thành quả in source) if (predicate(item)) yield return s; //codevar source = generateStrings();var seq = source.Where(s=> s.Length giờ thì hàm Where của bọn họ đã tương đối giống cùng với hàm Where vào Linq rồi. Nó có thể chấp nhận được bạn gọi hàm này với bất kỳ kiểu tài liệu nào, và chỉ còn ra súc tích lựa lựa chọn tại thời điểm gọi hàm. Trên thực tế, đoạn code này về cơ phiên bản là giống với hàm Where đích thực trong Linq(ngoại trừ một vài xúc tích và ngắn gọn kiểm tra điều kiện). Tuyệt!

Nếu tinh ý thì bạn cũng biến thành nhận ra rằng hàm Where của chúng ta là một hàm “thuần” (pure function), có nghĩa là nó không làm biến đổi dữ liệu. Điều này đúng cho toàn bộ các hàm vào Linq (tất nhiên, để nó thực thụ “thuần”, thì bạn dạng thân logic trong hàm “predicate” cũng không được làm biến đổi gì về dữ liệu). Một điểm độc đáo nữa của hàm Where là nó là một trong những hàm “lười” (lazy function), có nghĩa là tại thời gian bạn điện thoại tư vấn Where(), không có bất kể logic chọn lựa nào được thực hiện. Chỉ khi bạn tìm giải pháp đọc bộ phận của chuỗi IEnumerable cơ mà Where() trả về, dịp đó lô ghích “predicate” của người sử dụng mới bước đầu hoạt động.