Ответ
Итератор — это паттерн, позволяющий последовательно обходить элементы коллекции, не раскрывая её внутреннее устройство. В C# итераторы реализуются через интерфейсы IEnumerable (предоставляет перечислитель) и IEnumerator (непосредственно выполняет перебор).
Ключевое слово yield — это синтаксический сахар, который значительно упрощает создание итераторов. Компилятор автоматически генерирует класс, реализующий IEnumerable/IEnumerator, с сохранением состояния между шагами.
Основные понятия:
yield return— возвращает следующий элемент последовательности и приостанавливает выполнение метода до следующего вызоваMoveNext().yield break— завершает последовательность.- Ленивое выполнение: Элементы вычисляются только в момент запроса, что экономит память и CPU.
Пример: Генерация последовательности и фильтрация "на лету"
// Итератор, генерирующий бесконечную последовательность чисел Фибоначчи
public static IEnumerable<long> FibonacciSequence()
{
long a = 0, b = 1;
while (true)
{
yield return a; // Приостановка и возврат значения
long temp = a;
a = b;
b = temp + b;
}
}
// Итератор для фильтрации (пайплайн)
public static IEnumerable<int> GetEvenNumbers(IEnumerable<int> source)
{
foreach (int number in source)
{
if (number % 2 == 0)
{
yield return number; // Возвращаем только чётные
}
// Если число нечётное, просто пропускаем итерацию
}
}
// Использование:
// 1. Берём первые 10 чисел Фибоначчи
var firstTenFib = FibonacciSequence().Take(10);
// 2. Фильтруем их, оставляя только чётные
var evenFib = GetEvenNumbers(firstTenFib);
// 3. Материализуем результат (здесь происходит реальное вычисление)
foreach (var num in evenFib)
{
Console.WriteLine(num); // Выведет: 0, 2, 8, 34...
}
Важные ограничения:
- Методы с
yieldне могут содержатьreturn(кромеyield return/break). yield returnнельзя использовать внутриtry-catch, но можно внутриtry-finally(финальная часть выполнится при завершении перебора).