Ефективність
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 #. ІЛ, генерований для методу ітератора, різко відрізняється від того, що створюється для звичайного (не ітератора) методу. Ця стаття (Що насправді генерує ключове слово ?) Надає таке розуміння.