This is simple enough. If in each iteration you need index of the element, use "for". If you need to guarantee certain order of operations, use "for". In all other cases, try to use "foreach".
One delicate case is when you need to modify the set you are iterating during iterations, in particular, remove some elements, one approach is: using "for" iterating from high index to low index. Be very careful with such cases. Other, more complicated cases, need special consideration. In such cases, just use you logic.
Remember that exact behavior of "foreach" depends on how the interface
System.IEnumerable
is implemented, how its implementation of
System.Collections.IEnumerator
behaves. Please see:
https://msdn.microsoft.com/en-us/library/system.collections.ienumerable%28v=vs.110%29.aspx[
^],
https://msdn.microsoft.com/en-us/library/system.collections.ienumerable.getenumerator(v=vs.110).aspx[
^],
https://msdn.microsoft.com/en-us/library/system.collections.ienumerator%28v=vs.110%29.aspx[
^].
For one thing, it would be wise not to rely on any peculiar features known from a particular implementation of this interface. From the other hand, you can implement this interface in a specific way, to make some extra assumptions valid, but I would not recommend it.
If you want to say: "this answer pretty much says 'it depends', nothing else", this is essentially what it meant to be. :-)
[EDIT]
I later realized that my answer did not address some more specific problems of the question. So, please see Solution 2 and my comment to it.
—SA