Yield в C# — одна из тех мощных частей языка, которую редко понимают и редко применяют, но, как ни странно, это один из тех вопросов, которые, кажется, всплывают на многих собеседованиях.

Что Microsoft говорит о Yield

См. официальную строку Microsoft: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield.

Когда вы используете yield контекстное ключевое слово в операторе, вы указываете, что метод, оператор или get средство доступа, в котором оно появляется, является итератором. Использование yield для определения итератора устраняет необходимость в явном дополнительном классе (класс, который содержит состояние для перечисления, см. пример IEnumerator‹T›) при реализации шаблона IEnumerable и IEnumerator для пользовательский тип коллекции.

Что делает Yield

Выход или yield return позволяет вам возвращать значения (объекты) из итератора контролируемым образом, вы выбираете, что и когда будет возвращено вызывающему методу. Нам лучше просто показать код, чтобы получить представление.

Простой выход

Ниже приведен простой пример доходности. GetNumbers() содержит всего 4 строки кода yield return. Функция foreachmain запрашивает число, а for и yield возвращает число, как только это будет сделано, он переходит к следующему числу. В приведенном ниже примере мы используем возврат доходности для каждого значения, стоит отметить, что доходность возврата определяет, какое число передается обратно вызывающему методу.

Метод должен быть итератором, поэтому обычно используйте IEnumerable.
Итератор вызывается с помощью цикла, такого как foreach (хорошо, linq может работать, но на самом деле это тоже просто цикл).

Вывод

Account Number:  1
Account Number:  2
Account Number:  3
Account Number:  4

Более полезный пример, показывающий некоторую силу

Скажем, вы работаете в банке и вам нужно обновить всех клиентов в определенном месте и дать им 1% годовых. Вам сказали, что клиентов много и нужно смотреть производительность по системе и БД. Таким образом, вы хотите загружать данные о клиентах только непосредственно перед их изменением и не хотите загружать все данные о клиентах сразу.

Таким образом, вы можете использовать Iterator с IEnumerable с yield для циклического просмотра номеров счетов.

Пример ниже

  1. Загружает все номера учетных записей клиентов в List‹int›, хранение 20 000 целых чисел довольно эффективно по сравнению с 20 000 полных записей клиентов, и записи клиентов могут изменить баланс, прежде чем вы дойдете до конца списка.
  2. Загружает одну запись клиента для нашего вымышленного репозитория.
  3. Обновить баланс и обновить запись.
  4. Получите следующую запись клиента и повторите до завершения.

суть здесь: https://gist.github.com/FrankKerrigan/338f18266767e1f2ea2be46006e8a7c4

Резюме

Yield действительно очень полезен, хотя приведенный выше пример с банком имеет некоторые реальные проблемы, он дает хорошее понимание того, что вы можете управлять ресурсами и, по сути, лениво загружать данные и загружать их только в том случае, если они вам нужны.