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: