Doku says

Initially, the enumerator is positioned before the first element in the collection. […] Therefore, you must call the MoveNext method to advance the enumerator to the first element of the collection before reading the value of Current.

If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false. […]

C# Language Specification (8.8.4: The foreach statement)

The order in which foreach traverses the elements of an array, is as follows: For single-dimensional arrays elements are traversed in increasing index order, starting with index 0 and ending with index Length – 1. For multi-dimensional arrays, elements are traversed such that the indices of the rightmost dimension are increased first, then the next left dimension, and so on to the left.

Problem

Well, it’s a question of interpretation: Does MoveNext set to the next element in the collection or only to the next element (regardless to its position in the collection)? Only the behavior when dealing with arrays is specified unambiguously.

There could be a class implementing (for whatever the reason) GetEnumerator like follows:

However, this is no solution if you are using a dictionary; thanks to SeeQuark for informing me about this. In this case, if you really need a well-definied order, you’ll have to add an index to the elements in it.

Generalization / Best Practise:

Do not rely on the order elements will be returned by an iterator. As the foreach-loop uses one, the same applies to it. Foreach-loops using a counter variable in order to determine the index of each element should be replaced with for-loops.

Reading through the postings there (and answering them, of course ;-)) I sometimes think that there definitely have to be other people with the same problem without knowing it.

That means those problems are really hidden logical mistakes which are mainly caused by inaccurate usage of types or language features. In most cases they won’t catch somebody’s eye as their impacts only come to light under special (unfortunate) circumstances. Then, however, they are really difficult to find. You could say: They are no real bugs but they may cause bugs.

So I decided to start this new column which I’ll try to keep alive as long as this blog will exist. I hope, you’ll like it. 🙂