Hiệu quả
Các yield
từ khóa có hiệu quả tạo ra một liệt kê lười biếng trên mục bộ sưu tập có thể được hiệu quả hơn. Ví dụ: nếu foreach
vòng lặp của bạn lặp lại chỉ trong 5 mục đầu tiên của 1 triệu mục thì đó là tất cả yield
lợi nhuận và bạn đã không xây dựng bộ sưu tập 1 triệu mục trong nội bộ trước. Tương tự như vậy, bạn sẽ muốn sử dụng yield
với IEnumerable<T>
các giá trị trả về trong các kịch bản lập trình của riêng bạn để đạt được hiệu quả tương tự.
Ví dụ về hiệu quả đạt được trong một kịch bản nhất định
Không phải là một phương pháp lặp, tiềm năng sử dụng không hiệu quả của một bộ sưu tập lớn,
(Bộ sưu tập trung gian được xây dựng có rất nhiều mục)
// Method returns all million items before anything can loop over them.
List<object> GetAllItems() {
List<object> millionCustomers;
database.LoadMillionCustomerRecords(millionCustomers);
return millionCustomers;
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in GetAllItems()) {
num++;
if (num == 5)
break;
}
// Note: One million items returned, but only 5 used.
Phiên bản lặp, hiệu quả
(Không có bộ sưu tập trung gian được xây dựng)
// Yields items one at a time as the caller's foreach loop requests them
IEnumerable<object> IterateOverItems() {
for (int i; i < database.Customers.Count(); ++i)
yield return database.Customers[i];
}
// MAIN example ---------------------
// Caller code sample:
int num = 0;
foreach(var itm in IterateOverItems()) {
num++;
if (num == 5)
break;
}
// Note: Only 5 items were yielded and used out of the million.
Đơn giản hóa một số kịch bản lập trình
Trong một trường hợp khác, nó làm cho một số loại sắp xếp và hợp nhất các danh sách trở nên dễ dàng hơn để lập trình bởi vì bạn chỉ cần yield
sắp xếp lại theo thứ tự mong muốn thay vì sắp xếp chúng vào một bộ sưu tập trung gian và hoán đổi chúng trong đó. Có nhiều kịch bản như vậy.
Chỉ cần một ví dụ là hợp nhất hai danh sách:
IEnumerable<object> EfficientMerge(List<object> list1, List<object> list2) {
foreach(var o in list1)
yield return o;
foreach(var o in list2)
yield return o;
}
Phương pháp này mang lại một danh sách các mục liên tục, thực sự là một sự hợp nhất không cần bộ sưu tập trung gian.
Thêm thông tin
Các yield
từ khóa chỉ có thể được sử dụng trong bối cảnh của một phương pháp lặp (có một kiểu trả về của IEnumerable
, IEnumerator
, IEnumerable<T>
, hoặc IEnumerator<T>
.) Và có một mối quan hệ đặc biệt với foreach
. Lặp đi lặp lại là phương pháp đặc biệt. Các tài liệu năng suất MSDN và iterator tài liệu chứa rất nhiều thông tin thú vị và giải thích các khái niệm. Hãy chắc chắn để tương quan với các foreach
từ khóa bằng cách đọc về nó quá, để bổ sung hiểu biết của bạn lặp.
Để tìm hiểu về cách các trình vòng lặp đạt được hiệu quả của chúng, bí mật nằm ở mã IL được tạo bởi trình biên dịch C #. IL được tạo cho một phương thức iterator khác rất nhiều so với phương thức được tạo cho một phương thức (không lặp) thông thường. Bài viết này (Từ khóa năng suất thực sự tạo ra cái gì?) Cung cấp loại hiểu biết đó.