Намагаючись зберегти речі "простими", .NET має лише одну загальну / негенеричну пару інтерфейсів для речей, які перераховуються за допомогою виклику, GetEnumerator()
а потім використання MoveNext
та Current
отримання об'єкта, отриманого від нього, хоча існує як мінімум чотири види об'єктів який повинен підтримувати лише такі методи:
- Речі, які можна перерахувати хоча б один раз, але не обов'язково більше, ніж це.
- Речі, які можна перераховувати довільно кількість разів у контекстах із безкоштовним потоком, але можуть довільно отримувати різний вміст кожного разу
- Речі, які можна перераховувати довільно кількість разів у контекстах з безкоштовними потоками, але можуть гарантувати, що якщо код, який їх перераховує повторно, не викликає жодних мутуючих методів, усі перерахування повертають однаковий вміст.
- Речі, які можна перераховувати в довільній кількості разів, і гарантовано повертати один і той же вміст кожен раз, поки вони існують.
Будь-який екземпляр, який задовольняє одному з визначень з більшими числами, задовольнятиме також і всі нижчі, але код, для якого потрібен об'єкт, що задовольняє одному з вищих визначень, може порушитися, якщо задати одне з нижчих.
Схоже, Microsoft вирішила, що класи, які реалізують, IEnumerable<T>
повинні відповідати другому визначенню, але не зобов'язані задовольняти щось вище. Можливо, існує не так багато причин, що щось, що могло б відповідати лише першому визначенню, має реалізовувати, IEnumerable<T>
а не IEnumerator<T>
; якщо foreach
цикли можуть прийняти IEnumerator<T>
, то для речей, які можна перерахувати лише один раз, було б сенсом просто реалізувати останній інтерфейс. На жаль, типи, які реалізуються лише IEnumerator<T>
, менш зручні у використанні у C # та VB.NET, ніж типи, у яких є GetEnumerator
метод.
У будь-якому випадку, навіть якщо це було б корисно, якби були різні перелічені типи речей, які могли б дати різні гарантії, та / або стандартний спосіб запитати екземпляр, який реалізує IEnumerable<T>
те, що може дати гарантій, таких типів ще не існує.