Is there some rare language construct I haven't encountered (like the few I've learned recently, some on Stack Overflow) in C# to get a value representing the current iteration of a foreach loop?
For instance, I currently do something like this depending on the circumstances:
int i=0;
foreach (Object o in collection)
{
// ...
i++;
}
This would work for collections supporting
IList
.It's only going to work for a List and not any IEnumerable, but in LINQ there's this:
@Jonathan I didn't say it was a great answer, I just said it was just showing it was possible to do what he asked :)
@Graphain I wouldn't expect it to be fast - I'm not entirely sure how it works, it could reiterate through the entire list each time to find a matching object, which would be a helluvalot of compares.
That said, List might keep an index of each object along with the count.
Jonathan seems to have a better idea, if he would elaborate?
It would be better to just keep a count of where you're up to in the foreach though, simpler, and more adaptable.
There's nothing wrong with using a counter variable. In fact, whether you use
for
,foreach
while
ordo
, 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:
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 forList<T>
(the documentation doesn't say), but not necessarily for other types (such asLinkedList
)):It should never be necessary to 'manually' operate the
IEnumerator
by invokingMoveNext()
and interrogatingCurrent
-foreach
is saving you that particular bother ... if you need to skip items, just use acontinue
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:
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 aForEach()
extension method onList<T>
andArray
... and it's not clear that using it is any better than doing a simpleforeach
, since you are still running single-threaded for uglier syntax.I don't believe there is a way to get the value of the current iteration of a foreach loop. Counting yourself, seems to be the best way.
May I ask, why you would want to know?
It seems that you would most likley be doing one of three things:
1) Getting the object from the collection, but in this case you already have it.
2) Counting the objects for later post processing...the collections have a Count property that you could make use of.
3) Setting a property on the object based on its order in the loop...although you could easily be setting that when you added the object to the collection.
Just add your own index. Keep it simple.
I disagree with comments that a
for
loop is a better choice in most cases.foreach
is a useful construct, and not replaceble by afor
loop in all circumstances.For example, if you have a DataReader and loop through all records using a
foreach
it automatically calls the Dispose method and closes the reader (which can then close the connection automatically). This is therefore safer as it prevents connection leaks even if you forget to close the reader.(Sure it is good practise to always close readers but the compiler is not going to catch it if you don't - you can't guarantee you have closed all readers but you can make it more likely you won't leak connections by getting in the habit of using foreach.)
There may be other examples of the implicit call of the
Dispose
method being useful.