How
Internally, most of the base collection classes maintain a version number. Whenever you add, remove, reorder, etc the collection, this version number is incremented.
When you start enumerating, a snapshot of the version number is taken. Each time around the loop, this version number is compared against the collection's, and if they are different then this exception is thrown.
Why
Whilst it would be possible to implement IList
so that it could correctly deal with changes to the collection made within the foreach loop (by having the enumerator track the collection's changes), it is a much harder task to correctly deal with changes made to the collection by other threads during the enumeration. So this exception exists to help identify vulnerabilities in your code, and to provide some kind of early warning about any potential instabilities brought about by manipulation from other threads.