Я хочу поговорить о ключевом слове yield в C#. Я думаю, что это мощная функция C#, и я хотел подчеркнуть ее преимущества.

Ключевое слово yield сообщает компилятору, что метод, в котором оно появляется, является блоком итератора. Блок итератора или метод возвращает в качестве результата IEnumerable. И ключевое слово yield используется для возврата значений для IEnumerable.

Интересная особенность IEnumerable заключается в том, что он вычисляется лениво. Вызов метода с блоком итератора не запускает никакого кода. Только когда IEnumerable повторяется или перечисляется, мы получаем фактические значения. Я расскажу об этом позже.

Давайте посмотрим, как мы можем начать использовать ключевое слово yield.

Как использовать ключевое слово доходности

Ключевое слово yield само по себе ничего не делает, его нужно комбинировать с оператором return или break:

  • yield return — предоставляет следующее значение итератора.
  • yield-break — сигнализирует об окончании итерации.

В каждом проекте, над которым я работал, есть фрагмент кода, подобный следующему. Вы создаете список для хранения результатов, добавляете элементы в список и возвращаете список в конце.

Вы можете упростить метод, используя оператор yield return, и полностью удалить промежуточный список, необходимый для хранения результатов.

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

Остановка итерации с разрывом доходности

Вы можете использовать оператор yield break, чтобы остановить итерацию и выйти из блока итератора. Обычно вы делаете это, когда выполняется определенное условие, или вы хотите вернуть только определенный набор значений из блока итератора.

Вот пример, где это было бы полезно:

Работа с IAsyncEnumerable

В C# 8 мы получили тип IAsyncEnumerable, который позволяет нам асинхронно перебирать коллекцию с оператором yield.

Например, это может быть полезно, когда вы хотите несколько раз вызывать сторонний API для получения некоторых данных. Распространенная ситуация — когда вы получаете список пользователей из базы данных, а затем вам приходится вызывать службу внешнего хранилища, чтобы получить информацию об изображении профиля.

Без IAsyncEnumerable вам пришлось бы сделать что-то вроде этого:

Теперь рассмотрим тот же пример с использованием IAsyncEnumerable:

Вторая реализация будет перебирать пользователей, возвращаемых из базы данных, когда они выдаются IAsyncEnumerable.

Когда следует использовать доходность?

Я нашел несколько интересных практических применений ключевого слова yield. Одним из примеров является реализация объектов значений Domain-Driven Design.

Объекты-значения должны поддерживать структурное равенство. Им нужно реализовать метод, который возвращает все компоненты равенства. Вот пример использования оператора yield return:

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

Вы можете поддержать меня, купив мне чашку кофе. Купи мне кофе

Еще увидимся! Будьте счастливы и счастливы в программировании! -:)