Query Execution
Immediate Execution
The following sample shows how queries can be executed immediately, and their results stored in memory, with methods such as ToList.
Code:
public void Linq100()
{
// Methods like ToList(), Max(), and Count() cause the query to be
// executed immediately.
int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int i = 0;
var immediateQuery = (numbers.Select(num => ++i)).ToList();
Log.WriteLine("The current value of i is {0}", i); //i has been incremented
foreach (var item in immediateQuery)
{
Log.WriteLine("v = {0}, i = {1}", item, i);
}
}
Result:
Query Reuse
The following sample shows how, because of deferred execution, queries can be used again after data changes and will then operate on the new data.
Code:
public void Linq101()
{
// Deferred execution lets us define a query once
// and then reuse it later in various ways.
int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var lowNumbers = numbers.Where(num => num <= 3);
Log.WriteLine("First run numbers <= 3:");
foreach (int n in lowNumbers)
{
Log.WriteLine(n);
}
// Query the original query.
var lowEvenNumbers = lowNumbers.Where(p => p % 2 == 0);
Log.WriteLine("Run lowEvenNumbers query:");
foreach (int n in lowEvenNumbers)
{
Log.WriteLine(n);
}
// Modify the source data.
for (int i = 0; i < 10; i++)
{
numbers[i] = -numbers[i];
}
// During this second run, the same query object,
// lowNumbers, will be iterating over the new state
// of numbers[], producing different results:
Log.WriteLine("Second run numbers <= 3:");
foreach (int n in lowNumbers)
{
Log.WriteLine(n);
}
}
Result:
Deferred Execution
The following sample shows how query execution is deferred until the query is enumerated at a foreach statement.
Code:
public void Linq99()
{
// Queries are not executed until you enumerate over them.
int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int i = 0;
var simpleQuery = numbers.Select(num => ++i);
// The local variable 'i' is not incremented
// until the query is executed in the foreach loop.
Log.WriteLine("The current value of i is {0}", i); //i is still zero
foreach (var item in simpleQuery)
{
Log.WriteLine("v = {0}, i = {1}", item, i); // now i is incremented
}
}
Result: