Документация Microsoft для IEnumerable
[и IEnumerable<T>
- неуниверсальные имена будут относиться к обоим] рекомендует, чтобы каждый раз, когда объект, реализующий эти интерфейсы, изменялся, он должен был сделать недействительными любые экземпляры IEnumerator
[IEnumerator<T>
], который он ранее произвел, заставляя их бросать InvalidOperationException
при будущих попытках доступа. Хотя ничто в документации Microsoft не зафиксировало каких-либо изменений по сравнению с этой позицией, их фактические реализации IEnumerable
, похоже, следуют более слабому правилу, заключающемуся в том, что IEnumerator
не должен вести себя бессмысленно, если базовая коллекция изменена; он должен выбросить InvalidOperationException
, если он не может вести себя "разумно" . К сожалению, поскольку это правило не указано явно, а скорее вытекает из поведения их классов, неясно, что именно должно означать «разумное» поведение.
Все классы Microsoft, о которых я знаю, будут вызывать исключение при изменении коллекции, если они не могут соответствовать следующим критериям:
- Любой элемент, который существует неизменным в течение перечисления, будет возвращен ровно один раз.
- Элемент, который добавляется или удаляется во время перечисления, должен возвращаться не более одного раза, но если объект удаляется и повторно добавляется во время перечисления, каждое повторное добавление может рассматриваться как создание нового «элемента».
- Если коллекция гарантирует возврат вещей в отсортированной последовательности, эта гарантия должна выполняться, даже если элементы вставлены и удалены [например, если «Фред» добавлен в отсортированный по алфавиту список, а «Джордж» уже был перечислен, «Фред» не должен появляться во время этого перечисления].
Было бы полезно, если бы были какие-то средства, с помощью которых коллекции могли бы сообщать, могут ли они удовлетворять вышеуказанным критериям (без исключения), даже если они изменены, поскольку они могут быть очень полезны при попытке, например, удалить все предметы, которые соответствуют определенному критерию.