Интерфейс IEnumerable<T>
является фундаментом LINQ и всех операций с коллекциями в C#. Его определение:
public interface IEnumerable<out T> : IEnumerable
{
IEnumerator<T> GetEnumerator();
}
public interface IEnumerator<T> : IDisposable, IEnumerator
{
T Current { get; }
}
var numbers = Enumerable.Range(1, 10); // Не создает элементы сразу
foreach (var n in numbers) // Создание по требованию
{
Console.WriteLine(n);
}
foreach (var item in collection)
{
// Тело цикла
}
Преобразуется в:
var enumerator = collection.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
var item = enumerator.Current;
// Тело цикла
}
}
finally
{
(enumerator as IDisposable)?.Dispose();
}
public class FibonacciSequence : IEnumerable<long>
{
public IEnumerator<long> GetEnumerator()
=> new FibonacciEnumerator();
IEnumerator IEnumerable.GetEnumerator()
=> GetEnumerator();
private class FibonacciEnumerator : IEnumerator<long>
{
private long _current = 1;
private long _previous = 0;
public long Current => _current;
object IEnumerator.Current => Current;
public bool MoveNext()
{
var next = _current + _previous;
_previous = _current;
_current = next;
return true; // Бесконечная последовательность
}
public void Reset()
=> (_current, _previous) = (1, 0);
public void Dispose() { }
}
}
GetEnumerator()
создает новый итераторvar list = new List<int> { 1, 2, 3 };
var enumerator = list.GetEnumerator();
list.Add(4); // Изменяем коллекцию
enumerator.MoveNext(); // InvalidOperationException
public IEnumerable<int> GetOddNumbers(int max)
{
for (int i = 0; i <= max; i++)
{
if (i % 2 != 0)
yield return i; // Состояние сохраняется между вызовами MoveNext()
}
}
List<T>
реализует IEnumerable<T>
напрямуюpublic struct Enumerator : IEnumerator<T>
{
private readonly List<T> _list;
private int _index;
// Реализация методов
}
var result = collection
.Where(x => x > 0) // Не выполняется сразу
.OrderBy(x => x) // Не выполняется сразу
.Take(10); // Не выполняется сразу
foreach (var item in result) // Выполнение при итерации
Каждый элемент:
public async IAsyncEnumerable<int> GetDataAsync()
{
while (true)
{
var data = await FetchDataAsync();
yield return data;
}
}
await foreach (var item in GetDataAsync())
{
// Обработка
}
public class OptimizedEnumerable<T> : IEnumerable<T>
{
public IEnumerator<T> GetEnumerator()
=> new OptimizedEnumerator();
// Специальная реализация для Count(), Any() и т.д.
public int Count() => /* прямое вычисление */;
public bool Any() => /* проверка без полного перебора */;
}
IEnumerable<T>
работает через паттерн итератора, обеспечивая ленивое выполнение и эффективный обход коллекций. Реализация включает генераторы (yield
), специализированные энумераторы и поддержку LINQ. Понимание его работы критично для эффективной работы с коллекциями в .NET.