2

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:

  1. 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?
  2. 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...

Brummy
  • 183
  • 1
  • 11
  • 1
    You may want to read my Edulinq blog series: https://codeblog.jonskeet.uk/category/edulinq/ – Jon Skeet Jan 03 '17 at 12:38
  • Maybe this helps http://stackoverflow.com/questions/41257165/working-of-ienumerator-in-c-sharp/41257284#41257284 – wkl Jan 03 '17 at 12:39
  • 3
    Do you have specific problem or what exactly you do not understand? It would be easy to answer specific question, *under hood* is too broad. As for last part of your question, see [this](http://stackoverflow.com/q/3894490/1997232). – Sinatr Jan 03 '17 at 12:44

1 Answers1

0

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 at GetEnumerator().MoveNext() call.

  • Thank you for the reply. I take it the code/logic within the IEnumerable/IEnumerator is dynamically produced based on the syntax of the LINQ query? And it's _deferred_ because the data is not retrieved by the enumerator until the MoveNext is called (using the dynamically produced code to retrieve the data)? – Brummy Jan 03 '17 at 13:04
  • Something like this. LINQ query returns implementation of `IEnumerable` (e.g. `WhereEnumerableIterator` for `Where` query) that has inside source collection and predicate (or selector, or smth else depending on query type). And only when it is enumerated this logic is evaluated. – Oleksandr Kobylianskyi Jan 03 '17 at 13:15