Glossary / Iterator methods

Iterator methods

An iterator method produces a sequence incrementally through yield return and optionally ends it with yield break. The compiler transforms the method into a state machine that implements an enumeration protocol, allowing callers to request one item at a time without constructing the entire collection up front.

Execution and lifetime

Calling an iterator method typically creates an enumerable/iterator without executing the body; execution begins when enumeration requests an element. Each MoveNext resumes after the previous yield. finally blocks run when enumeration completes or is disposed, which is important for cleanup. Exceptions occur during enumeration rather than necessarily at method-call time.

static IEnumerable<int> CountTo(int max)
{
    for (int i = 1; i <= max; i++) yield return i;
}

Iterator methods cannot return by ref; restrictions apply to yield within try/catch/finally and unsafe/ref contexts, with rules evolving by language version. A returned iterator can be enumerated multiple times, often creating fresh state machines and repeating side effects. Async iterators combine async with yield return to implement IAsyncEnumerable<T>.

Engineering guidance

Use iterators for large/lazy sequences and composable streaming. Keep side effects and resource ownership clear, ensure enumerators are disposed, and avoid returning a sequence that captures a short-lived resource unexpectedly. Materialize when callers need stable repeated access.

Interview questions

  1. When does iterator body execute? During enumeration, generally when MoveNext is called.
  2. What does yield return do? Produces one element and suspends state until next request.
  3. When do finally blocks run? On completion or enumerator disposal, including early termination.
  4. Can exceptions occur at method invocation? Iterator body exceptions are generally deferred until enumeration.
  5. Why can repeated enumeration be risky? It reruns the iterator and any side effects or I/O.

References