Существуют ли неповторяющиеся классы IEnumerable?

Существуют ли неповторяющиеся классы IEnumerable?

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


person Jonathan Allen    schedule 29.11.2009    source источник
comment
Что вы имеете в виду под неповторяемостью? Судя по двум ответам, ваш вопрос неоднозначен.   -  person James Black    schedule 29.11.2009
comment
Счетчики не обязательно повторяются. Если ваши перечислители оборачивают поток, то вы не обязательно можете вызывать для него Reset. Но, поднимаясь на один уровень вверх, вы обычно можете вызывать GetEnumerator сколько угодно раз и всегда получать один и тот же результат. Но всегда ли вы можете вызывать GetEnumerator таким образом?   -  person Jonathan Allen    schedule 29.11.2009


Ответы (3)


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

person CodesInChaos    schedule 04.06.2011
comment
Что ж, нас ждет неприятный сюрприз. - person Jonathan Allen; 06.06.2011
comment
Я не уверен, что это по дизайну или ошибка в библиотеке. То, что он не выдает обычный InvalidOperationException, а передает ошибку, возникающую при доступе к удаленному текстовому читателю, вызывающей стороне, намекает на то, что это действительно может быть ошибка. - person CodesInChaos; 06.06.2011
comment
Вероятно, это была ошибка (или функция) в .NET 4.0. Я не могу воспроизвести это с .NET 4.5. - person Paolo Moretti; 14.09.2012
comment

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

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

person supercat    schedule 04.06.2011

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

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

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

person Guffa    schedule 29.11.2009
comment
Enumerable.Range вообще не создает элементы, о которых заботится Enumerable.Range.GetEnumerator. Поскольку перечислитель, который он возвращает, каждый раз имеет одни и те же начальные значения, он все равно будет считаться повторяемым. - person Jonathan Allen; 29.11.2009
comment
@Jonathan: Вы упускаете суть. Диапазон не повторяется, так как вы не можете повторно перечислить тот же диапазон, вам нужно создать новый диапазон. Поскольку метод Range возвращает не перечисляемый объект, а перечислитель, нет объекта, для которого можно было бы вызвать GetEnumerator для повторения перечисления. - person Guffa; 29.11.2009
comment
Почему минус? Если вы не объясните, что вы считаете неправильным в ответе, это не сможет его улучшить. - person Guffa; 05.06.2011
comment
Почему минус? Если вы не объясните, что вы считаете неправильным в ответе, это не сможет его улучшить. - person Guffa; 06.06.2011