foreach
is built on top of IEnumerable<T>
The contract for the enumerator on MSDN says
Initially, the enumerator is positioned before the first element in the collection. ... Therefore, you must call MoveNext to advance the enumerator to the first element of the collection before reading the value of Current.
Current returns the same object until MoveNext is called. MoveNext sets Current to the next element.
So if the underlying collection has clear 'first' element, and each element has a clear 'next' element, as is the case for arrays, lists and so on, then you can expect that the foreach
to behave logically and stably. If it is something like a set, which has no first or next sequence, then it may behave in an unstable manner, though presumably without changing the IEnumerable's state even collections which have no defined order will be consistent, as making them inconsistent would be more work!