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