Calling Count()
on an enumerable source will exhaust the enumerable until all elements are enumerated. Calling Count()
on an enumerable in the condition-block in a for loop will therefore exhaust the enumerable at every iteration. For example, calling
var numbers = VerboseRange(1, 5);
for (var index = 0; index < numbers.Count(); index++)
{
Console.WriteLine($"For-loop is at index {index}...");
}
IEnumerable<int> VerboseRange(int start, int count)
{
foreach (var number in Enumerable.Range(start, count))
{
Console.WriteLine($"Yielded number {number}.");
yield return number;
}
}
will output
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
For-loop is at index 0...
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
For-loop is at index 1...
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
For-loop is at index 2...
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
For-loop is at index 3...
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
For-loop is at index 4...
Yielded number 1.
Yielded number 2.
Yielded number 3.
Yielded number 4.
Yielded number 5.
Therefore, counting before is better.
However, I would recommend you to use a counter and a foreach
-loop
var count = 0;
foreach (var item in items)
{
// do something
count++;
}
In C# 7.0, you can finally do
foreach (var (item, index) in items.WithIndex())
{
// do something
}