Deferred Execution
An important feature of most query operators is that they execute
not when constructed, but when enumerated (in other
words, when MoveNext is called on its
enumerator). Consider the following query:
var numbers = new List<int>( ); numbers.Add (1); // Build query IEnumerable<int> query = numbers.Select (n => n * 10); numbers.Add (2); // Sneak in an extra element foreach (int n in query) Console.Write (n + "|"); // 10|20|
The extra number that we sneaked into the list
after constructing the query is included in the
result because it’s not until the foreach statement runs that any filtering or
sorting takes place. This is called deferred or
lazy evaluation. All standard query operators
provide deferred execution, with the following exceptions:
Operators that return a single element or scalar value, such as
FirstorCountThe following conversion operators:
ToArray, ToList, ToDictionary, ToLookup
These operators cause immediate query execution because their
result types have no mechanism for providing deferred execution. The
Count method, for instance, returns a
simple integer, which doesn’t then get enumerated. The following query
is executed immediately:
int matches = numbers.Where (n => n <2).Count(); // 1
Deferred execution is important because it decouples query construction from query execution. This allows you to construct a query in several steps, and it makes LINQ to SQL queries possible.
Note
Subqueries provide another level of indirection. Everything in a subquery ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access