An IEnumerable<T> is not a collection. It is a recipe. Every foreach follows the recipe again
from the beginning — and so does every Count(), every Any(), every First().
C#
static int _calls;
static IEnumerable<int> Source()
{
_calls++;
yield return 1;
yield return 2;
yield return 3;
}
static void Main()
{
var seq = Source();
Console.WriteLine(seq.Count());
Console.WriteLine(seq.Sum());
Console.WriteLine(_calls);
}
Output
3 6 2
Two enumerations, two runs. With three numbers that is invisible. With a database query, an HTTP call or a file read behind the iterator, it is a production incident.
How this shows up in real code
The classic version of this bug: a repository method returns IEnumerable<Order> backed by a
query. A caller writes if (orders.Any()) { foreach (var o in orders) ... } — and the query runs
twice. Nothing looks wrong in the code. The database sees double the load.
Try it: Task 1
Open the editor