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.Carsis 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
lambda0but something like<Main>b__0(whereMainis the name of the containing method). Similarly, the cached delegate is actually calledCS$<>9__CachedAnonymousMethodDelegate1.If you are using LINQ-to-SQL, then
db.Carswill be of typeIQueryable<Car>and this step is very different. It would instead turn the lambda expression into an expression tree:The
foreachloop is transformed into atry/finallyblock (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):