Существуют ли неповторяемые классы IEnumerable? - PullRequest
1 голос
/ 29 ноября 2009

Есть ли неповторяемые классы IEnumerable?

Под неповторяющимся я подразумеваю, когда вы не можете безопасно вызывать GetEnumerator несколько раз или когда вызов GetEnumerator имеет наблюдаемые побочные эффекты.

Ответы [ 3 ]

1 голос
/ 05 июня 2011

Реализации IEnumerable (Of T) могут вернуть любые элементы, которые они считают нужными, по любой причине. Вполне ожидаемо, что если кто-то дважды вызовет GetEnumerator для одной и той же последовательности элементов, а затем перейдет к циклу между обоими перечислителями, то они должны либо выдать одинаковые элементы в том же порядке, либо вызвать исключение. Существует ряд подпрограмм, которые принимают IEnumerable (Of T) и будут плохо работать, если даны те, которые не соблюдают такой контракт.

Если бы у меня были мои барабанщики, IEnumerable был бы разделен на семейство интерфейсов; базовый перечислитель IEnumerable потерял бы метод Reset и не дал бы никаких конкретных обещаний повторяемости. Новый IMultiEnumerable возвращает перечислитель с методом Reset и гарантией того, что несколько проходов дадут одинаковые данные; перечислитель может также поддерживать свой собственный метод GetEnumerator (я думаю, что это должно быть практично для любого типа, который может поддерживать многопроходное перечисление; единственной стоимостью будет указатель 'start', поэтому вложенный перечислитель будет сброшен в местоположение его оригинала создание).

1 голос
/ 05 июня 2011

File.ReadLines() возвращает IEnumerable<T>, который работает только один раз.

0 голосов
/ 29 ноября 2009

Нет, любой класс с хорошим поведением, который реализует IEnumerable, допускает повторные перечисления.

Для перечисления коллекций, которые не повторяются, у вас нет класса, реализующего IEnumerable. Вместо этого у вас есть метод, который возвращает перечислитель. Таким образом, перечислитель вместо класса содержит коллекцию, поэтому невозможно вызвать GetEnumerator дважды для одной и той же коллекции. Чтобы повторить перечислитель, вы должны вызвать метод для создания новой коллекции.

Примером этого является Enumerable.Range метод. Он создает элементы для диапазона на лету, поэтому диапазон не существует как коллекция, что делает его неповторимым. Чтобы снова перечислить тот же диапазон, вы вызываете метод для создания нового диапазона с такими же границами.

...