Существуют ли неповторяющиеся классы IEnumerable?
Под неповторяемостью я подразумеваю случаи, когда вы не можете безопасно вызывать GetEnumerator несколько раз или когда вызов GetEnumerator имеет наблюдаемые побочные эффекты.
Существуют ли неповторяющиеся классы IEnumerable?
Под неповторяемостью я подразумеваю случаи, когда вы не можете безопасно вызывать GetEnumerator несколько раз или когда вызов GetEnumerator имеет наблюдаемые побочные эффекты.
File.ReadLines()
возвращает IEnumerable<T>
, который работает только один раз.
InvalidOperationException
, а передает ошибку, возникающую при доступе к удаленному текстовому читателю, вызывающей стороне, намекает на то, что это действительно может быть ошибка.
- person CodesInChaos; 06.06.2011
Реализации IEnumerable(Of T) могут возвращать любые элементы, которые они считают подходящими, по любой причине. Вполне ожидаемо, что если дважды вызвать GetEnumerator для одной и той же последовательности элементов, а затем перейти к циклическому просмотру обоих перечислителей, они должны либо выдать одни и те же элементы в одном и том же порядке, либо выдать исключение. Существует ряд подпрограмм, которые принимают IEnumerable(Of T) и потерпят неудачу, если они не соблюдают такой контракт.
Если бы у меня были свои барабанщики, IEnumerable был бы разделен на семейство интерфейсов; базовый перечислитель IEnumerable потерял бы метод Reset и не давал бы особых обещаний повторяемости. Новый IMultiEnumerable вернет перечислитель с методом Reset и гарантией того, что несколько проходов дадут идентичные данные; перечислитель также может поддерживать свой собственный метод GetEnumerator (я думаю, что это должно быть практичным для любого типа, который может поддерживать многопроходное перечисление; единственной ценой будет указатель «начало», поэтому вложенный перечислитель будет сброшен в исходное местоположение творчество).
Нет, любой хорошо себя зарекомендовавший класс, реализующий IEnumerable
, допускает повторные перечисления.
Для перечисления неповторяемых коллекций у вас нет класса, реализующего IEnumerable
. Вместо этого у вас есть метод, который возвращает перечислитель. Таким образом, перечислитель вместо класса содержит коллекцию, поэтому невозможно дважды вызвать GetEnumerator
для одной и той же коллекции. Чтобы повторить перечислитель, вы должны вызвать метод для создания новой коллекции.
Примером этого является метод Enumerable.Range
. Он создает элементы для диапазона на лету, поэтому диапазон не существует как коллекция, что делает его неповторяемым. Чтобы снова перечислить тот же диапазон, вы вызываете метод для создания нового диапазона с теми же границами.