В попытке сделать вещи «простыми», .NET имеет только одну универсальную / неуниверсальную пару интерфейсов для вещей, которые перечисляются путем вызова, GetEnumerator()
а затем с использованием MoveNext
и Current
на полученном от них объекте, хотя существует по крайней мере четыре вида объектов который должен поддерживать только те методы:
- Вещи, которые можно перечислить хотя бы один раз, но не обязательно более того.
- Вещи, которые можно перечислять произвольное количество раз в контексте с произвольной резьбой, но каждый раз могут произвольно выдавать разное содержимое
- Вещи, которые можно перечислить произвольное количество раз в контекстах со свободной резьбой, но могут гарантировать, что если код, который их перечисляет многократно, не вызывает никаких методов мутации, все перечисления будут возвращать один и тот же контент.
- Вещи, которые могут быть перечислены произвольное количество раз и гарантированно возвращать одно и то же содержимое каждый раз, пока они существуют.
Любой экземпляр, который удовлетворяет одному из определений с более высокими номерами, также будет удовлетворять всем более низким, но код, который требует объекта, удовлетворяющего одному из более высоких определений, может сломаться, если ему дано одно из более низких определений.
Похоже, что Microsoft решила, что классы, которые реализуют, IEnumerable<T>
должны удовлетворять второму определению, но не обязаны удовлетворять чему-то более высокому. Возможно, нет особой причины, по которой что-то, что могло бы соответствовать только первому определению, должно быть реализовано, IEnumerable<T>
а не IEnumerator<T>
; если бы foreach
циклы могли принять IEnumerator<T>
, было бы разумно для вещей, которые можно перечислить только один раз, просто реализовать последний интерфейс. К сожалению, типы, которые только реализуют IEnumerator<T>
, менее удобны для использования в C # и VB.NET, чем типы, у которых есть GetEnumerator
метод.
В любом случае, даже если было бы полезно, если бы существовали разные перечислимые типы для вещей, которые могли бы давать разные гарантии, и / или стандартный способ запроса экземпляра, который реализует, IEnumerable<T>
какие гарантии он может дать, таких типов еще не существует.