Deferred Query Evaluation
A LINQ query is not evaluated when it is defined but when it is used. Consider the following query definition:
This code declares a very simple query that contains just two items, as shown by the result of the following line of code:
Now we want to change the content of the source sequence by adding a new customer:
If you enumerate the expr variable again or just check its item count, you will find a result different than before, as you can see when executing the code in Listing 4-55.
Listing 4-55: Example that shows when expression trees are evaluated
Console.WriteLine("\nItems after source sequence modification: {0}", expr.Count());
foreach (var item in expr) {
Console.WriteLine(item);
}
The result of the code in Listing 4-55 looks like the following. The new customer, Roberto, is included in the result, even though it has been added after the expr query definition:
|
Important |
From a logical point of view, a LINQ query describes a kind of “query plan” because it is not executed until it is used and will be executed again and again, every time you run it. Some LINQ implementations-such as LINQ to Objects-implement this behavior through delegates, while others-such as LINQ to SQL-might use expression trees. We call this behavior “deferred query evaluation,” and it is a fundamental concept in LINQ, regardless of its implementation.
|
Deferred query evaluation is useful because you can define queries once and apply them several times. Regardless of whether the source sequence has been changed, the result will always be updated to the last sequence content. However, consider a situation in which you want a snapshot of the result at a particular “safe point” to use many times, even if the source sequence changes in the meantime. You need to make a copy of the result, and conversion operators will help you do that.