Ефективність
yieldКлючове слово ефективно створює ліниве перерахування по пунктам збору , які можуть бути набагато більш ефективним. Наприклад, якщо ваш foreachцикл повторює лише перші 5 елементів з 1 мільйона предметів, то це все yieldповертається, і ви спочатку не створили колекцію з 1 мільйона предметів. Так само ви хочете використовувати yieldз IEnumerable<T>поверненими значеннями у власних сценаріях програмування для досягнення тієї ж ефективності.
Приклад ефективності, досягнутої за певним сценарієм
Не метод ітератора, потенційне неефективне використання великої колекції
(Проміжний збірник побудований з великою кількістю предметів)
// 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.
Версія ітератора, ефективна
(проміжний збірник не побудований)
// 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.
Спростіть деякі сценарії програмування
В іншому випадку деякі види сортування та об’єднання списків простіше програмувати, тому що ви просто yieldповертаєте елементи в потрібному порядку, а не сортуєте їх у проміжну колекцію та заміняєте їх там. Таких сценаріїв багато.
Лише одним із прикладів є злиття двох списків:
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;
}
Цей метод дає назад один суміжний список предметів, фактично злиття без проміжного збору.
Більше інформації
yieldКлючове слово може бути використано тільки в контексті методу ітератора (має тип повернення IEnumerable, IEnumerator, IEnumerable<T>, або IEnumerator<T>.) , І є особливі відносини з foreach. Ітератори - це спеціальні методи. Документація про вихід MSDN та документація ітераторів містять багато цікавої інформації та пояснень понять. Переконайтеся , співвіднести його з по foreachключовим словом , прочитавши про це теж, щоб доповнити ваше розуміння ітератори.
Щоб дізнатися про те, як ітератори досягають своєї ефективності, секрет полягає в коді IL, згенерованому компілятором C #. ІЛ, генерований для методу ітератора, різко відрізняється від того, що створюється для звичайного (не ітератора) методу. Ця стаття (Що насправді генерує ключове слово ?) Надає таке розуміння.