Как я могу использовать IEnumerator.Reset()?
Как правильно выбрать способ IEnumerator.Reset
?
В документации написано:
Метод Reset
предоставляется для взаимодействия COM. Это необязательно должно быть реализовано; вместо этого разработчик может просто выбросить 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()) { ... }
}
Это то, как мы должны использовать его? Или мы не должны использовать его из управляемого кода?
Ответы
Ответ 1
никогда; в конечном счете это было ошибкой. Правильный способ повторить последовательность более одного раза - снова вызвать .GetEnumerator()
- например, снова использовать foreach
. Если ваши данные не повторяются (или дорогие для повторения), буферируйте его с помощью .ToList()
или аналогичного.
В спецификации языка формальное требование заключается в том, что итератор блокирует исключения для этого метода. Таким образом, вы не можете полагаться на это, работая. Когда-нибудь.
Ответ 2
Я не рекомендую его использовать. Множество современных реализаций IEnumerable
просто выбросит исключение.
Получение перечислителей вряд ли "дорого". Он перечисляет их всех (полностью), которые могут быть дорогими.
Ответ 3
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();
}
}
}
}