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.

Note

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

Get LINQ Pocket Reference now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.