TGViewer
Библиотека шарписта | C#, F#, .NET, ASP.NET Библиотека шарписта | C#, F#, .NET, ASP.NET @csharpproglib · 21.7K subscribers
Post #7081 2.42K
🤩 Паттерн, который компилятор реализует за вас

Паттерн Iterator позволяет обходить коллекцию, не раскрывая её внутреннюю структуру. Классическая реализация на C# требовала ручного написания IEnumerator<T> с методами MoveNext(), Reset() и свойством Current.

Это выглядело громоздко. Даже для простого обхода приходилось писать отдельный класс, хранить состояние, следить за позицией. Десятки строк кода ради того, чтобы пройтись по элементам.

Как это выглядело раньше:
public class NumberCollection : IEnumerable<int>
{
private readonly int[] _items = { 1, 2, 3, 4, 5 };

public IEnumerator<int> GetEnumerator()
{
return new NumberEnumerator(_items);
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public class NumberEnumerator : IEnumerator<int>
{
private readonly int[] _items;
private int _position = -1;

public NumberEnumerator(int[] items)
{
_items = items;
}

public int Current => _items[_position];
object IEnumerator.Current => Current;

public bool MoveNext()
{
_position++;
return _position < _items.Length;
}

public void Reset() => _position = -1;
public void Dispose() { }
}


Отдельный класс, ручное управление индексом, реализация IDisposable. И всё это ради последовательного перебора массива.

Что изменил `yield return`

Теперь компилятор умеет генерировать всю эту машину состояний самостоятельно. Вы пишете yield return, а компилятор создаёт класс с MoveNext(), Current и корректным управлением состоянием за вас.

Тот же результат в несколько строк:
public static IEnumerable<int> GetNumbers()
{
yield return 1;
yield return 2;
yield return 3;
yield return 4;
yield return 5;
}


Обход ленивый. Каждый элемент вычисляется только при запросе. Это важно, когда вы работаете с большими или бесконечными последовательностями:
public static IEnumerable<int> EvenNumbers()
{
int n = 0;
while (true)
{
yield return n;
n += 2;
}
}

// Берём первые 10 чётных чисел
var result = EvenNumbers().Take(10).ToList();


Попробуйте реализовать бесконечную последовательность через ручной IEnumerator. Код будет работать, но читать его будет заметно сложнее.

Связка с LINQ

yield return хорошо сочетается с LINQ. Можно строить цепочки обработки, где каждый шаг выполняется лениво:
public static IEnumerable<string> ProcessUsers(IEnumerable<User> users)
{
foreach (var user in users)
{
if (user.IsActive)
yield return user.Name.ToUpper();
}
}

// Или через LINQ
var names = users
.Where(u => u.IsActive)
.Select(u => u.Name.ToUpper());


Оба варианта ленивые. Ни один не создаёт промежуточных коллекций, пока вы не вызовете ToList(), foreach или другой терминальный оператор.

Когда ручной итератор всё ещё нужен

Есть случаи, где yield return не подойдёт. Например, если нужен асинхронный обход с отменой, сложная логика очистки ресурсов при досрочном прерывании, или обход нетривиальных структур вроде графов с контролем состояния обхода. В таких ситуациях ручная реализация IEnumerator<T> или IAsyncEnumerator<T> оправдана.

Но для большинства задач yield return закрывает вопрос полностью. Компилятор C# решил эту задачу ещё в 2005 году. Если вы пишете ручной итератор для простого обхода коллекции, стоит проверить, не делаете ли вы работу, которую компилятор готов взять на себя.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека шарписта

#il_люминатор
  • ❤ 8
  • 👍 8
More from @csharpproglib
  1. Sep 22, 2026💡 Replace, Regex или StringBuilder? Для замены текста в C# есть несколько инструментов. И…
  2. Sep 21, 2026⚙️ Настоящие атомарные операции Если Volatile решает проблему видимости, то Interlocked ре…
  3. Sep 20, 2026💪 Разминка перед трудовыми буднями Что произойдёт? ❤️ — список станет [1, 3] 🔥 — Invalid…
  4. Sep 19, 2026🧩 Middleware в ASP.NET Core: 3 ловушки Middleware — звено HTTP pipeline: app.Use(async (c…
  5. Sep 18, 2026📍 Навигация: Вакансии • Задачи • Собесы 🐸Библиотека шарписта #garbage_collector
  6. Sep 17, 2026🦆 Duck typing в C# — почти как в TypeScript В TypeScript достаточно, чтобы у объекта был…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →