After reading various LINQ tutorials I am wondering how exactly it works under the hood and I am hoping someone could confirm some of the questions I have with the following example code:
// The Three Parts of a LINQ Query:
// 1. Data source.
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
// 2. Query creation.
// numQuery is an IEnumerable<int>
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
// 3. Query execution.
foreach (int num in numQuery)
{
Console.Write("{0,1} ", num);
}
My questions refer to part 2:
- Here we are using LINQ syntax to create an IEnumerable object. Is this no different to any other IEnumerable object used within a foreach statement, such as List?
- As with all IEnumerables the contents are iterated over using a foreach statement. My query comes from LINQ IEnumerables using deferred execution - when are the contents of the IEnumerable actually gathered? Is it when the GetEnumerator() is called?
With question 2 my assumption would be that the object generated from the LINQ query produces code within the GetEnumerator function which retrieves the data in a fashion represented by our LINQ syntax. Just my guess... Unless I'm thinking about LINQ completely wrong...
Both of your questions are closely related.
So, yes, there is a difference. LINQ query operator return decorator sequences and this decoration enables deferred execution. Decorator sequence is a wrapper over another sequence (
int[]
in your case) that also knows which query to apply on wrapped sequence. Actual execution occurs atGetEnumerator().MoveNext()
call.