16. Оператор yield return. Интерфейс IEnumerable.

yield return

Ключевое слово yield используется в итераторах для поочерёдного возвращения значения вместо отдельного класса, хранящего состояние перечисления.

yield return используется для возврата каждого элемента коллекции по очереди путем применения оператора foreach или запроса LINQ. Каждая итерация цикла foreach вызывает метод итератора. При достижении в методе итератора оператора yield return возвращается выражение, стоящее после него и сохраняется текущее расположение в коде. При следующем вызове функции итератора выполнение возобновляется с этого места.

Для завершения итерации можно использовать оператор yield break.

Важно заметить, что использовать yield можно только в итераторах

Объявление итератора должно соответствовать следующим требованиям:

  • Возвращаемый тип должен быть System.Collections.IEnumerable, System.Collections.Generic.IEnumerable, System.Collections.IEnumerator или System.Collections.Generic.IEnumerator

  • Объявление не должно содержать параметры ref и out.

Тип yield итератора, который возвращает System.Collections.IEnumerable или System.Collections.IEnumerator, — object. Если итератор возвращает System.Collections.Generic.IEnumerable или System.Collections.Generic.IEnumerator, необходимо выполнить неявное преобразование из типа выражения в операторе yield return в параметр универсального типа.

Методы, в которых операторы yield return и yield break использовать нельзя:

  • Анонимные методы. Дополнительные сведения см. в разделе Анонимные методы.

  • Методы, содержащие небезопасные (unsafe) блоки.

Оператор yield return нельзя размещать в блоке try-catch. Оператор yield return можно размещать в блоке try оператора try-finally.

Оператор yield break можно размещать в блоке try или catch, но не в блоке finally.

Если тело оператора foreach (вне метода итератора) вызывает исключение, выполняется блок finally в методе итератора.

Пример

В следующем примере имеется оператор yield return, расположенный в цикле for. Каждая итерация тела оператора foreach создает вызов функции итератора getRange. При каждом вызове функции итератора происходит переход к следующему выполнению оператора yield return, которое осуществляется во время следующей итерации цикла for.

Тип возвращаемого значения метода итератора — System.Collections.IEnumerable. При вызове метода итератора возвращается перечисляемый объект, содержащий числа на заданном участке массива.

public class YieldExample
{
    static void Main()
    {
        int[] arrayOfNumbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
        foreach (int i in getRange(arrayOfNumbers, 2, 4))
        {
            Console.Write("{0} ", i);
        }
    }

    public static System.Collections.Generic.IEnumerable<int> getRange(int[] numbers, int start, int end)
    {
        for (int i = start; i <= end; i++)
        {
            int result  = numbers[i];
            yield return result;
        }
    }
    // Вывод: 3 4 5
}

Интерфейс IEnumerable

IEnumerable является базовым интерфейсом для всех неуниверсальных перечислимых коллекций. Универсальная версия этого интерфейса - System.Collections.Generic.IEnumerable<T>. IEnumerable содержит только один метод GetEnumerator, который возвращает IEnumerator. IEnumerator позволяет выполнять итерации по коллекции, предоставляя свойство Current и методы MoveNext и Reset.

Рекомендуется реализовать IEnumerable и IEnumerator в пользовательских классах коллекций, чтобы использовать синтаксис foreach, однако реализация IEnumerable не является обязательной. Если в вашей коллекции не реализован IEnumerable, по-прежнему необходимо реализовать итератор для поддержки синтаксиса foreach, предоставляя метод GetEnumerator, возвращающий интерфейс, класс или структуру. Необходимо указать класс, содержащий свойство Current, и методы MoveNext и Reset, описанные в IEnumerator, но при этом класс может не реализовывать интерфейс IEnumerator.

results matching ""

    No results matching ""