I think the documentation referenced in the answer is extremely misleading. The order of For Each
is defined by the collection it's called (i.e. its implementation of IEnumerable
/IEnumerable<T>
), but that's not the same as saying it shouldn't be used when the order is important. Many collections (such as arrays, List<T>
etc) always go in the "natural" order.
Part of the documentation does allude to this:
Traversal Order. When you execute a
For Each...Next loop, traversal of the
collection is under the control of the
enumerator object returned by the
GetEnumerator method. The order of
traversal is not determined by Visual
Basic, but rather by the MoveNext
method of the enumerator object. This
means that you might not be able to
predict which element of the
collection is the first to be returned
in element, or which is the next to be
returned after a given element.
That's not at all the same as saying it can't be relied upon - it can be relied upon if you know that the collection you're iterating over will produce the results in the desired order. It's not like it's going to pick elements at random. The behaviour in terms of IEnumerable
/IEnumerable<T>
is clearly defined on that page.
The most important exceptions to predictable orderings are dictionaries and sets, which are naturally unordered.
To reverse an IEnumerable<T>
, use Enumerable.Reverse
- but if you need to iterate in reverse over a collection which is indexed by position (such as an array or List<T>
) then it would be more efficient to use a For
loop starting at the end and working backwards.