Все мы знаем, что цикл foreach был разработан для чтения коллекции, а не для записи в нее.

Вот почему следующее приводит к InvalidOperationException:

Как он отслеживает изменения в коллекции?

Это делается с помощью int с именем _version в классе List<T>.

_version увеличивается каждый раз при обновлении коллекции, то есть в следующих методах:

  • Метод установки индексатора
  • Add()
  • Clear()
  • Insert()
  • InsertRange()
  • RemoveAll()
  • RemoveAt()
  • RemoveRange()
  • Reverse()
  • Sort()

Когда List<T> перечисляется в foreach, вызывается метод GetEnumerator(), который возвращает экземпляр структуры с именем Enumerator.

Enumerator имеет свою собственную переменную version, которая инициализируется только один раз со значением из List<T>._version и никогда не изменяется.

Во время каждой итерации в foreach вызывается метод MoveNext(), который проверяет, совпадает ли List<T>._version с version.

Если они не совпадают, генерируется исключение:

Прочтите эту статью, чтобы узнать интересный способ обойти это исключение.