Everything so far has been a cost. Here is the payoff: because an iterator only computes what is asked for, it can describe a sequence that has no end.
static IEnumerable<int> Naturals()
{
for (int i = 1; ; i++)
{
yield return i;
}
}
That for loop has no exit condition. Written anywhere else it would hang the program. Here it is
harmless, because it only advances when someone calls MoveNext.
foreach (var n in Naturals().Take(5))
{
Console.WriteLine(n);
}
Output
1 2 3 4 5
Take(5) stops asking after the fifth value, so the loop stops running. The sixth number is never
computed — it does not exist anywhere.
Fibonacci, without deciding how many
The usual version of this function takes a count parameter, because it has to know how big an
array to fill. An iterator does not have to know.
static IEnumerable<long> Fibonacci()
{
long a = 0;
long b = 1;
while (true)
{
yield return a;
long next = a + b;
a = b;
b = next;
}
}
The one way to hurt yourself
Never call Count(), ToList(), Last() or OrderBy() on an infinite sequence. Each of them has
to reach the end, and there is no end — the program hangs. Bound it first with Take, TakeWhile
or First.
Try it: Task 1
Open the editor