For example:
var query = from c in db.Cars select c;
foreach(Car aCar in query)
{
Console.WriteLine(aCar.Name);
}
How would this translate once it is compiled? What happens behind the scenes?
For example:
var query = from c in db.Cars select c;
foreach(Car aCar in query)
{
Console.WriteLine(aCar.Name);
}
How would this translate once it is compiled? What happens behind the scenes?
It is compiled in the following way:
First, the LINQ query expression is transformed into method calls:
If
db.Cars
is of typeIEnumerable<Car>
(which it is for LINQ-to-Objects), then the lambda expression is turned into a separate method:In reality the method is not called
lambda0
but something like<Main>b__0
(whereMain
is the name of the containing method). Similarly, the cached delegate is actually calledCS$<>9__CachedAnonymousMethodDelegate1
.If you are using LINQ-to-SQL, then
db.Cars
will be of typeIQueryable<Car>
and this step is very different. It would instead turn the lambda expression into an expression tree:The
foreach
loop is transformed into atry/finally
block (this is the same for both):Finally, this is compiled into IL the expected way. The following is for
IEnumerable<Car>
:The compiled code for the
IQueryable<Car>
version is also as expected. Here is the important part that is different from the above (the local variables will have different offsets and names now, but let’s disregard that):