Deferred vs Immediate Execution
Most LINQ operators — Where, Select, OrderBy, GroupBy — use deferred execution: writing var query = list.Where(x => x.Runs > 50) does not filter anything yet; it just builds a query object describing what to do. The filtering only happens when something enumerates the query, such as a foreach loop. Other operators — ToList(), ToArray(), Count(), Sum(), First(), Max() — use immediate execution: they force the query to run right then and return a concrete result or collection.
Cricket analogy: Like a bowling change that a captain announces but only actually happens when the umpire calls 'play', a deferred LINQ query like var q = list.Where(x => x.Runs > 50) is only defined, not executed, until something enumerates it — such as a foreach loop.
Deferred Execution in Action
Because deferred operators like Where re-evaluate their predicate against the live source every time the query is enumerated, results can change between two enumerations of the same query variable if the underlying collection was modified in between. This is a common source of confusion: a developer assumes a query variable holds a fixed result set, when in fact it holds a re-runnable plan that reflects whatever the source collection looks like at the moment of enumeration.
Cricket analogy: Like re-checking the required run rate every single over because it recalculates from the current score each time, a deferred query such as var lowScores = scores.Where(s => s < 20) re-evaluates against the live list every time you foreach over it, picking up any changes made in between.
Immediate Execution in Action
Calling a materializing operator — ToList(), ToArray(), ToDictionary() — or a value-producing operator — Count(), Sum(), First(), Max() — forces the entire deferred query to run right away and captures the results as a fixed snapshot. From that point on, the resulting List<T> or scalar value is completely independent of the source collection; later changes to the source have no effect on it.
Cricket analogy: Like locking in the final scorecard the moment the umpires call stumps, calling .ToList() on a deferred query forces immediate execution and captures a fixed snapshot of results at that instant, unaffected by later changes to the source list.
Common Pitfalls
Two mistakes trip up developers repeatedly. First, enumerating the same deferred query multiple times — once in a foreach, once in a Count() call — re-executes the entire pipeline each time, wasting CPU on expensive filters or hitting a database twice. The fix is to materialize once with .ToList() and reuse that list. Second, modifying a collection (adding or removing items) while a deferred query over it is being enumerated throws an InvalidOperationException: 'Collection was modified; enumeration operation may not execute.'
Cricket analogy: Like re-running DRS ball-tracking analysis from scratch every single time a commentator references it instead of caching the result, forgetting to call .ToList() on an expensive deferred query and then enumerating it twice re-executes the whole filter both times.
var names = new List<string> { "Ana", "Ben", "Cara" };
var query = names.Where(n => n.Length > 3); // deferred, nothing runs yet
names.Add("Diego"); // mutates the source before enumeration
foreach (var n in query)
Console.WriteLine(n); // prints "Diego" too — the query re-ran against the updated list
// Force immediate execution to snapshot results now
var snapshot = names.Where(n => n.Length > 3).ToList();
names.Add("Eshaan"); // no effect on 'snapshot'Adding or removing items from a List<T> while a foreach loop is enumerating a deferred query over that same list throws InvalidOperationException: Collection was modified; enumeration operation may not execute. Materialize with .ToList() first if you need to modify the source during iteration.
- Deferred execution (Where, Select, OrderBy, GroupBy) builds a query plan that runs only when enumerated.
- Immediate execution (ToList(), ToArray(), Count(), Sum(), First(), Max()) runs the query right away and returns a fixed result.
- Deferred queries re-evaluate against the live source every time they're enumerated, so results can change between enumerations.
- Enumerating an expensive deferred query multiple times re-executes the whole pipeline each time — materialize once with ToList() to avoid this.
- Modifying a source collection while enumerating a deferred query over it throws InvalidOperationException.
- Once materialized (e.g., via ToList()), a result is a fixed snapshot independent of later changes to the source.
Practice what you learned
1. Which of these LINQ operators uses deferred execution?
2. What happens if you enumerate the same deferred LINQ query twice without materializing it?
3. What exception is thrown if you add an item to a List<T> while a foreach loop is enumerating a deferred query over it?
4. How can you force a deferred LINQ query to execute immediately and capture a fixed snapshot?
5. Why might enumerating a deferred query over a database-backed IQueryable twice be a performance problem?
Was this page helpful?
You May Also Like
LINQ to Objects
LINQ to Objects is the flavor of LINQ that runs entirely in memory against IEnumerable<T> collections like arrays, List<T>, and Dictionary<T>, using compiled delegates rather than translated queries.
IQueryable vs IEnumerable
IEnumerable<T> executes LINQ queries in memory using compiled delegates, while IQueryable<T> builds expression trees that a provider like EF Core translates into a remote query — mixing them up can silently pull entire tables into memory.
What Is LINQ?
LINQ (Language Integrated Query) is a set of C# language and .NET library features that let you write strongly-typed queries against in-memory collections, databases, XML, and more using one unified syntax.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesMFC (Microsoft Foundation Classes) Study Notes
C++ · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics