Glossary / Deferred execution

Deferred execution

Deferred execution delays running a query or iterator until its results are requested. Many LINQ operators over IEnumerable<T> return a pipeline description that runs during enumeration, while terminal operators such as ToList, Count, and First execute immediately.

Behavior and consequences

var query = numbers.Where(n => n > threshold);
threshold = 10;
var results = query.ToList(); // predicate sees current threshold

The query may observe source mutations and captured-variable changes between construction and enumeration. Enumerating twice can repeat database calls, file reads, calculations, side effects, or exceptions. Some sources are single-use or stateful; others produce different results on each pass. IQueryable providers can also defer translation and execution until a terminal operation.

Deferred pipelines can reduce intermediate allocations and support streaming, but repeated enumeration and hidden side effects can be surprising. ToList or ToArray establishes a snapshot of the produced sequence at that point, consuming memory proportional to output.

Engineering guidance

Use deferred queries for simple, pure transformations consumed once. Materialize at clear ownership boundaries when repeatability, stable snapshots, or multiple passes are required. Avoid side effects inside Where/Select; expose execution explicitly and inspect query counts in data-access code.

Interview questions

  1. When does Where run? Usually during enumeration for IEnumerable<T>.
  2. What if enumerated twice? Work may run twice and results can differ.
  3. How capture state affects query? Captured values are read when the delegate executes, unless copied separately.
  4. What does materialization do? Executes now and stores results in memory.
  5. What is the tradeoff? Deferred streaming and lower intermediate storage versus hidden execution/repetition; materialization uses memory but stabilizes results.

References