← Назад к вопросам

Какие знаешь методы внутри IEnumerator?

1.7 Middle🔥 151 комментариев
#Основы C# и .NET

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Методы интерфейса IEnumerator в C#

Интерфейс IEnumerator является фундаментальным компонентом паттерна итератора в .NET и предоставляет два ключевых метода и одно свойство для последовательного перебора элементов коллекции.

Основные методы и свойство

  1. Свойство Current

    object Current { get; }
    

    Возвращает текущий элемент в последовательности. Вызывает исключение InvalidOperationException, если итератор находится в невалидном состоянии (до первого элемента или после последнего).

  2. Метод MoveNext()

    bool MoveNext();
    

    Перемещает итератор к следующему элементу коллекции. Возвращает:

    • true - если перемещение успешно
    • false - если достигнут конец коллекции
  3. Метод Reset()

    void Reset();
    

    Возвращает итератор в начальное положение (перед первым элементом). Важно: Этот метод является устаревшим и не поддерживается многими современными коллекциями.

Детальное объяснение методов

Метод MoveNext()

Это основной двигатель итерации. Его реализация включает:

public bool MoveNext()
{
    if (_position < _collection.Length - 1)
    {
        _position++;
        return true;
    }
    return false;
}

Ключевые особенности:

  • Должен быть вызван ПЕРЕД первым обращением к Current
  • После возврата false последующие вызовы также возвращают false
  • Итератор находится в одном из трех состояний:
    1. Перед коллекцией (initial state)
    2. Внутри коллекции (после успешного MoveNext)
    3. После коллекции (после возврата false из MoveNext)

Свойство Current

Тип возвращаемого значения - object, что требует приведения типов при использовании. В обобщенной версии IEnumerator<T> это ограничение снимается.

public object Current
{
    get
    {
        if (_position < 0 || _position >= _collection.Length)
            throw new InvalidOperationException();
        
        return _collection[_position];
    }
}

Метод Reset()

Исторически использовался для повторной итерации, но сейчас считается проблемным:

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

Проблемы с Reset():

  • Не все коллекции могут быть "сброшены" (например, итераторы по потокам данных)
  • Многие реализации просто бросают NotSupportedException
  • Рекомендуется создавать новый итератор вместо использования Reset()

Пример полной реализации

public class ArrayEnumerator : IEnumerator
{
    private object[] _array;
    private int _position = -1;
    
    public ArrayEnumerator(object[] array)
    {
        _array = array;
    }
    
    public object Current
    {
        get
        {
            if (_position == -1 || _position >= _array.Length)
                throw new InvalidOperationException();
            return _array[_position];
        }
    }
    
    public bool MoveNext()
    {
        _position++;
        return _position < _array.Length;
    }
    
    public void Reset()
    {
        _position = -1;
    }
}

Сравнение с IEnumerator<T>

В современном C# чаще используется обобщенный интерфейс:

public interface IEnumerator<out T> : IEnumerator, IDisposable
{
    new T Current { get; }
}

Преимущества IEnumerator<T>:

  • Типобезопасность (не требует приведения типов)
  • Добавлен метод Dispose() для освобождения ресурсов
  • Ковариантность (out parameter)

Паттерн использования

Стандартный шаблон работы с итератором:

IEnumerator enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
    object item = enumerator.Current;
    // обработка элемента
}

Поддерживаемые коллекции и синтаксический сахар

Большинство коллекций .NET реализуют IEnumerator:

  • Массивы и List<T>
  • Dictionary<TKey, TValue>
  • Queue<T> и Stack<T>
  • LINQ-запросы (отложенное выполнение)

Синтаксический сахар foreach автоматически использует IEnumerator:

foreach (var item in collection) 
{
    // компилятор генерирует код с MoveNext() и Current
}

Best Practices

  1. Всегда используйте using с IEnumerator<T> для гарантированного вызова Dispose()
  2. Избегайте Reset() - создавайте новый итератор при необходимости повторного прохода
  3. Не модифицируйте коллекцию во время итерации - это приведет к InvalidOperationException
  4. Для параллельных коллекций используйте специализированные итераторы с поддержкой конкурентного доступа

Понимание работы IEnumerator критически важно для эффективной работы с коллекциями в C# и создания собственных перечислимых типов данных.