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