КПД
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 #. IL, сгенерированный для метода итератора, кардинально отличается от того, который генерируется для обычного (не итераторного) метода. В этой статье («Что в действительности генерирует ключевое слово доходность?») Дается такое понимание.