Modern C# · Lesson 10

Iterator methods

Produce sequence elements when a consumer requests them.

How it works

An iterator method returns a sequence by using yield return. Calling Squares creates an enumerable operation; it does not eagerly calculate and store every square. Enumeration enters the body and advances until the next yielded value. Take requests only the first two items, so the loop does not need to produce the square of three. This supports pipelines that can stop early.

It also means side effects inside an iterator happen during enumeration and can happen again when the sequence is enumerated again. Keep the iterator’s input and lifetime requirements clear, especially if its body accesses mutable data.

Add a diagnostic WriteLine immediately before yield return and observe how Take stops requests. Enumerate the same query twice and count how many diagnostic messages appear.

A working example

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

foreach (var square in Squares(4).Take(2)) Console.WriteLine(square);
IEnumerable<int> Squares(int count)
{
    for (var i = 1; i <= count; i++) yield return i * i;
}

Expected output

1
4
Try this
An iterator describes how to obtain values; enumeration asks for them.