There's nothing wrong with using a counter variable. In fact, whether you use for
, foreach
while
or do
, a counter variable must somewhere be declared and incremented.
So use this idiom if you're not sure if you have a suitably-indexed collection:
var i = 0;
foreach (var e in collection) {
// Do stuff with 'e' and 'i'
i++;
}
Else use this one if you know that your indexable collection is O(1) for index access (which it will be for Array
and probably for List<T>
(the documentation doesn't say), but not necessarily for other types (such as LinkedList
)):
// Hope the JIT compiler optimises read of the 'Count' property!
for (var i = 0; i < collection.Count; i++) {
var e = collection[i];
// Do stuff with 'e' and 'i'
}
It should never be necessary to 'manually' operate the IEnumerator
by invoking MoveNext()
and interrogating Current
- foreach
is saving you that particular bother ... if you need to skip items, just use a continue
in the body of the loop.
And just for completeness, depending on what you were doing with your index (the above constructs offer plenty of flexibility), you might use Parallel LINQ:
// First, filter 'e' based on 'i',
// then apply an action to remaining 'e'
collection
.AsParallel()
.Where((e,i) => /* filter with e,i */)
.ForAll(e => { /* use e, but don't modify it */ });
// Using 'e' and 'i', produce a new collection,
// where each element incorporates 'i'
collection
.AsParallel()
.Select((e, i) => new MyWrapper(e, i));
We use AsParallel()
above, because it's 2014 already, and we want to make good use of those multiple cores to speed things up. Further, for 'sequential' LINQ, you only get a ForEach()
extension method on List<T>
and Array
... and it's not clear that using it is any better than doing a simple foreach
, since you are still running single-threaded for uglier syntax.
foreach
is to provide a common iteration mechanism for all collections regardless of whether they are indexable (List
) or not (Dictionary
). – Brian GideonDictionary
isn't indexable, an iteration ofDictionary
does traverse it in a particular order (i.e. an Enumerator is indexable by the fact it yields elements sequentially). In this sense, we could say that we are not looking for the index within the collection, but rather the index of the current enumerated element within the enumeration (i.e. whether we are at the first or fifth or last enumerated element). – Matt Mitchell