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 First or Count

  • The 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.


Subqueries provide another level of indirection. Everything in a subquery ...

Get LINQ Pocket Reference now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.