Sự kết hợp giữa ienumerable và yield trong c#

Khi sử dụng C# để thiết kế, bạn có thể đang bắt gặp tự khóa yield rất nhiều lần tuy vậy rất ít khi chúng ta hiểu rằng nó là gì cùng bao gồm tác dụng như nào? Hôm nay, mình đã chia sẻ cùng với chúng ta rất nhiều gọi biết của bản thân về yield, khôn cùng ao ước phần nhiều share này vẫn hữu ích cho các bạn trên tuyến phố thành master C# nhé.

You watching: Sự kết hợp giữa ienumerable và yield trong c#

Trước Lúc nói về trường đoản cú khóa yield, họ thuộc nhắc lại về IEnumerable.

1. IEnumerable là gì

IEnumerable là một trong danh sách gồm những nằm trong tính sau:- Danh sách chỉ gọi, ko được phxay thêm/bớt phần tử- Chỉ coi sóc một chiều từ trên đầu cho tới cuối danh sách. Sử dụng foreach để thực hiện duyệt

Các chúng ta cũng có thể xem thêm tại nội dung bài viết "IEnumerable và IEnumerator vào C#" tại phía trên.

2. Yield là gì

Yield là trường đoản cú khóa đã báo hiệu mang lại trình biên dịch biết rằng cách làm, tân oán tử, get mà lại nó mở ra sẽ là một trong khối hận lặp. Trình biên dịch đang tự động hóa sinh ra một class implement tự IEnumerable, IEnumerator để mô tả khối hận lặp đó.

Chúng ta hãy xét ví dụ sau:

class Program private static IEnumerable Ints() for (var i = 0; i Sau Khi biên dịch lịch sự file exe cộ cùng dịch trở lại file exe pháo kia, bọn họ thu được class nlỗi sau:

internal class Program // Methods private static IEnumerable Ints() this.5__1 = 0; while (this.5__1 5__1; int numét vuông = this.5__1; this.5__1 = numét vuông + 1; private static void Main(string<> args) foreach (int num in Ints()) Console.WriteLine(num); Console.ReadKey(); // Nested Types private sealed class d__1 : IEnumerable, IEnumerable, IEnumerator, IDisposable, IEnumerator // Fields private int 1__state; private int 2__current; private int l__initialThreadId; private int 5__1; // Methods public d__1(int 1__state) this.1__state = 1__state; this.l__initialThreadId = Environment.CurrentManagedThreadId; private bool MoveNext() switch (this.1__state) case 0: this.1__state = -1; this.5__1 = 0; while (this.5__1 2__current = this.5__1; this.1__state = 1; return true; Label_003F: this.1__state = -1; int num2 = this.5__1; this.5__1 = numét vuông + 1; return false; case 1: gokhổng lồ Label_003F; return false; IEnumerator IEnumerable.GetEnumerator() if ((this.1__state == -2) && (this.l__initialThreadId == Environment.CurrentManagedThreadId)) this.1__state = 0; return this; return new Program.d__1(0); IEnumerator IEnumerable.GetEnumerator() => this.System.Collections.Generic.IEnumerable.GetEnumerator(); void IEnumerator.Reset() throw new NotSupportedException(); void IDisposable.Dispose() // Properties int IEnumerator.Current => this.2__current; object IEnumerator.Current => this.2__current; Giờ chúng ta lưu ý:HàmIEnumerable Ints() tất cả xuất hiện thêm từ bỏ khóa yield với được gán thêm ở trong tínhIteratorStateMachine(typeof(d__1)), cùng với thuộc tính này trình biên dịch sẽ xác thực hàm bên trên là 1 trong những kăn năn lặp (hoặc có thể hotline là state machine).Classd__1 được trình biên dịch hình thành, implement từ IEnumerable, IEnumerator nhằm triển khai mang đến khối lặp trên.

3. Cách sử dụng

Từ khóa yield được áp dụng vào 2 trường hợp nlỗi sau:

yield return ;yield break;Lưu ý:- Đối với hàm hoặc get thực hiện từ khóa yield bắt buộc phải trả về phong cách dữ liệu là IEnumerable, IEnumerable, IEnumerator hoặc IEnumerator.- Sử dụng trong khoảng lặp có ĐK (nếu như không tồn tại ĐK thì trả luôn danh sách phải không tính ngôi trường vừa lòng này).- Lưu trạng thái của lần lặp trước.ví dụ như bọn họ bao gồm danh sách tất cả 10 thành phần trường đoản cú 0 đến 9 nhỏng sau:

private static List MyList = new List 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ;3.1. yield returnNếu là hàm ko áp dụng yield thì khi return, chương trình đã thoát ra khỏi hàm kia.Nếu là hàm sử dụng yield return thì lịch trình đang trả về tài liệu với quay trở về vòng lặp để tiến hành vòng lặp tiếp theo.Chúng ta coi ví dụ liệt kê các thành phần có giá trị to hơn 3 bằng 2 biện pháp nlỗi sau:

class Program private static List MyList = new List 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ; private static IEnumerable NoneYield() var d = new List(); foreach (var nhà cửa in MyList) if (sản phẩm > 3) d.Add(item); return d; private static IEnumerable UseYield() foreach (var chiến thắng in MyList) if (cửa nhà > 3) yield return item; static void Main(string<> args) Console.WriteLine("None Yield"); foreach (var công trình in NoneYield()) Console.WriteLine(item); Console.WriteLine("Yield"); foreach (var thành tựu in UseYield()) Console.WriteLine(item); Console.ReadKey(); Kết trái đã nlỗi sau:

*
Nếu không thực hiện yield, để trả về list nhỏng trên, họ yêu cầu tạo thành một list trợ thời nhằm giữ số đông bộ phận vừa lòng ĐK, sau khi lưu giữ không còn rất nhiều bộ phận kia new thực hiện return.Nếu áp dụng yield thì sau thời điểm yield return, chương trình tiến hành tiếp vòng foreach tiếp theo sau.

3.2. yield break

Nếu vòng lặp sử dụng break, Khi gặp lệnh break, công tác chỉ thoát khỏi vòng lặp, đa số cái phía sau với quanh đó vòng lặp vẫn được thực hiện.Nếu vòng lặp áp dụng yield break, lịch trình đang thoát khỏi hàm cơ mà ko triển khai các lệnh phía dưới.Chúng ta xét bài bác toán: liệt kê những phần tử khác 3 (Lúc chạm mặt quý hiếm 3 thì dừng):

class Program private static List MyList = new List 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ; private static IEnumerable NoneYield() var d = new List(); foreach (var vật phẩm in MyList) if (thành tích != 3) d.Add(item); else break; Console.WriteLine("Done"); // Sử dụng chiếc này để rành mạch return d; private static IEnumerable UseYield() foreach (var nhà cửa in MyList) if (tác phẩm != 3) yield return item; else yield break; Console.WriteLine("Done"); // Sử dụng dòng này nhằm phân biệt static void Main(string<> args) Console.WriteLine("None Yield"); foreach (var thành công in NoneYield()) Console.WriteLine(item); Console.WriteLine("=============================================="); Console.WriteLine("Yield"); foreach (var nhà cửa in UseYield()) Console.WriteLine(item); Console.ReadKey(); Và công dụng vẫn nhỏng sau:

*
lúc áp dụng break thì lộ diện cái chữ "Done", còn yield break thì không.

4. Một số chú ý Khi sử dụng

4.1. Lúc sử dụng yield, họ đề xuất tuân thủ một số trong những kinh nghiệm sau:

Không sử dụng yield trong khối lệnh tất cả từ bỏ khóa unsafe cùng vào hàm ẩn danh.

See more: Download Game Sniper Ghost Warrior 3 Công Bố Cấu Hình “Khó Thở”

Không thực hiện từ bỏ khóa ref hoặc out đi kèm theo với tsay mê số của hàm lúc bên trong hàm thực hiện yield.yield return chỉ được áp dụng trong try catch có finally.yield break được sử dụng vào try catch không tồn tại finally.Chỉ cần áp dụng yield Một trong những trường thích hợp ĐK trả về không quá phức hợp. Bản hóa học của vấn đề áp dụng yield là có mặt class nhằm thực hiện kăn năn lặp. Trong kăn năn lặp này còn có thực hiện đoạn mã để đánh giá điều kiện. Nếu vấn đề chất vấn này quá phức tạp đã tác động trực tiếp tới hiệu năng của áp dụng.4.2. So sánh tốc độ thân return và yield return

Chúng ta hãy xem ví dụ sau: trả về danh sáchmột triệu bộ phận thực hiện 2 phương thức là không sử dụng yield với có sử dụng yield

class Program { private static IEnumerable NoneYield() { var d = new List(); for (var i = 0; i UseYield() { for (var i = 0; i Chúng ta hãy xem kết quả:

*
quý khách hàng hãy thực hiện chạy các lần để xem các hiệu quả khác nhau. Trung bình bọn họ đang chiếm được là tốc độ cách xử trí của hàm có yield vội vàng ít nhất 10 lần. Một số lượng thiệt khủng khiếp.

4.2. yield return giữ gìn trạng thái của lần lặp trước

Chúng ta hãy xét ví dụ sau:

class Program { private static IEnumerable UseYield() { var total = 1; // 5 for (var i = 0; i Với đoạn code bên trên người nào cũng nghĩ về công dụng lúc hiển thị ra màn hình là:

12345Nhưng lúc chạy công tác đã mang lại hiệu quả là:

*

Ohh, cthị trấn gì xảy ra vậy? Sao công dụng lại là 1 trong những 2 4 7 11??? Chúng ta hãy đặt breakpoint tại cái 1, 3, 5, 6, 8 và test debug coi công việc thực hiện:Bước 1: Thực hiện nay chạy chương trình cho cái 1, liên tục triển khai đã khiêu vũ mang đến loại 5 => trở thành total được gán là 1.Cách 2: Bắt đầu vòng lặp cùng gán i = 0, liên tiếp triển khai đến cái 8 => thay đổi total = total + i => có mức giá trị 1 với yield return quý giá 1. Tiếp tục thực hiện đã in 1 ra màn hình hiển thị.Bước 3: Tiếp tục tiến hành vòng lặp loại 1, thường xuyên triển khai sẽ khiêu vũ mang lại dòng 6 => với cái giá trị i = 1. Tiếp tục tiến hành total = total + i = 2 => yield return cực hiếm 2. Tiếp tục triển khai sẽ in 2 ra screen.Bước 4: Tiếp tục thực hiện vòng lặp mẫu 1, liên tục triển khai sẽ nhảy mang lại cái 6 => với giá trị i = 2. Tiếp tục thực hiện total = total + i = 4 => yield return giá trị 4. Tiếp tục tiến hành vẫn in 4 ra screen.Từ đoạn này chúng ta thấy rằng vấn đề gán trở thành total = 1 chỉ ra mắt 1 lần, giá trị này được tái thực hiện mang đến lần lặp tiếp sau. Như vậy phân tích và lý giải mang lại Việc gìn giữ tinh thần Khi áp dụng yield.Bước 5: quá trình được tái diễn cho đến i = 4.

See more: 1 Triệu Đậu Bigo Đổi Được Bao Nhiêu Tiền? ? Cách Đổi Tiền Bigo Live

Tạm kết

Trên đây tôi đã giới thiệu cùng với các bạn về tự khóa Yield, cách thức áp dụng cùng các xem xét khi làm việc cùng với yield. Hi vọng bài viết hữu ích với các bạn. Nếu có gì còn vướng mắc, hãy giữ lại comment nhé.