Как я могу использовать IEnumerator.Reset ()? - PullRequest
34 голосов
/ 11 мая 2011

Как правильно позвонить IEnumerator.Reset?

В документации сказано:

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

Хорошо, значит ли это, что я никогда не должен это называть?* заманчиво использовать исключения для управления потоком:

using (enumerator = GetSomeExpensiveEnumerator())
{
    while (enumerator.MoveNext()) { ... }

    try { enumerator.Reset(); } //Try an inexpensive method
    catch (NotSupportedException)
    { enumerator = GetSomeExpensiveEnumerator(); } //Fine, get another one

    while (enumerator.MoveNext()) { ... }
}

Это то, как мы должны его использовать?Или мы вообще не должны использовать его из управляемого кода?

Ответы [ 3 ]

48 голосов
/ 11 мая 2011

никогда ;в конечном итоге это была ошибка.Правильный способ повторения последовательности более одного раза - это снова вызвать .GetEnumerator(), то есть снова использовать foreach.Если ваши данные неповторяемые (или дорогостоящие для повторения), поместите их в буфер с помощью .ToList() или подобного.

Это формальное требование в спецификации языка, что блоки итератора выдают исключения дляЭтот метод.Таким образом, вы не можете полагаться на то, что он работает .Когда-либо.

8 голосов
/ 11 мая 2011

Я рекомендую не использовать его.Во многих современных IEnumerable реализациях просто возникнет исключение.

Получение перечислителей вряд ли когда-либо будет "дорогим".Это перечисление их всех (полностью), которые могут быть дорогими.

1 голос
/ 29 апреля 2014
public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element 
    // until the first MoveNext() call. 
    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

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

    object IEnumerator.Current
    {
        get
        {
            return Current;
        }
    }

    public Person Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}
...