What is deferred vs immediate execution in LINQ?
Quick Answer
Deferred operators (Where, Select, OrderBy, Take) build a pipeline and don't run until you enumerate. Immediate operators (ToList, ToArray, Count, First, Sum, Any) execute the query right away. A deferred query re-runs every time you iterate it.
Most LINQ operators are deferred — Where, Select, OrderBy just build up a query and don't actually do anything until something forces execution. The forcing operators are ToList, Count, First, Any, Sum and so on. The trap is that a deferred query re-runs every time you enumerate it — so if I loop over an IEnumerable once to get the count and again to process it, that's two database round trips with EF. The fix is a single ToList() when I need the results more than once.
- Because a deferred query re-executes, iterating it twice means two DB hits (with EF) or two full passes (LINQ to Objects) — a common performance and correctness bug (“multiple enumeration”).
- A deferred query also sees changes to the source made after it was defined.
- Call
ToList()once when you need a stable snapshot or will iterate more than once. - Resharper/analyzers warn on “possible multiple enumeration of IEnumerable”.