In 8.8.4 of the C# specification, it provides this example:
A foreach statement of the form
foreach (V v in x) embedded-stat
There is special-case code in the compiler which enforces the read-only constraint on the iteration variable in a foreach
block. It does not correspond to any modifier which is exposed in the language, so you can't explicitly declare local variables as read-only outside of this particular syntax.
Conceptually, this constraint is applied before the expansion. That is, if there are any assignments to the iteration variable, the compiler generates an error. Otherwise the code is expanded. In the expanded code there is no particular constraints on v
since it is just a regular local variable. Therefore the constraint does not exist in the IL either.
So why is there this special-case read-only constraint with the foreach
-syntax? Only the language designers can answer that, but I would guess it is just to avoid confusion. If the iterator variable was assignable, you might think you were able to modify the actual collection that way, but nothing would actually happen, since the underlying enumerator is read-only.