Sunday, January 20, 2008

Demystifying C# 3.0 - Part 6: (LINQ) Query Expression Translation (to C# 3.0)

Source: http://blah.winsmarts.com/2006/05/21/demystifying-c-30--part-6-linq-query-expression-translation-to-c-30.aspx
Demystifying C# 3.0 - Part 6: (LINQ) Query Expression Translation (to C# 3.0)
Posted on 6/30/2006 @ 8:47 PM in #Vanilla .NET 7 comments 5310 views
In this series of Demystifying C# 3.0 we have already covered -
a) Demystifying C# 3.0 - Part 1: Implicitly Typed Local Variables "var"b) Demystifying C# 3.0 - Part 2: Anonymous Typesc) Demystifying C# 3.0 - Part 3: Extension Methodsd) Demystifying C# 3.0 - Part 4: Lambda Expressionse) Demystifying C# 3.0 - Part 5: Object and Collection Initializers
I *strongly* recommend reading up the above in sequence before reading this post. This is, (I feel) a rather good post, that will set LINQ in your mind clearly. If you rush through this post, you will waste this opportunity. If you are crystal clear about the above 5 posts and the concepts behind them, .. read on ..
Okay good, so in this post, we are going to talk about "Queries" or "LINQ" for the very first time in this Demystifying C# series. I have been asked in comments to talk about the practical application of the new C# 3.0 thingies. I can come up with seemingly lame practical applications, because the real awesome practical application - IS - LINQ (Language Integrated Query).
The practical application of the above 5 C# 3.0 features (which are not the complete set of new things in C# 3.0), can best be understood by understanding Query Expression Translation.
LINQ, as you may already know, looks like TSQL queries, except they are twisted upside down, and written in right inside of C#. You have probably already heard about the benefits, so I won't go into those for now. In here, we are going to talk about Query Expression Translation. You can write queries in LINQ using various keywords such as "from", "where", "select" etc.
Those queries, get translated into plain vanilla C# 3.0 code, and only then type-binding, overload resolution etc. happens. Once the Query has been translated to C#, it is then executed as regular method invocations - where of course you have various C# protections such as a method being missing, data types mismatched so on and so forth.
So, LINQ --> Query --> TranslatedToC#3.0 --> Method Invocation.
So LINQ = Method Invocation? YES - THAT IS WHAT MAKES LINQ, Nothing but Plain vanilla C# 3.0. All those new language constructs, along with Query Expression Translation, make LINQ possible.
Lets understand with the help of an example.
In my last post Demystifying C# 3.0 - Part 5: Object and Collection Initializers, I had a simple example demonstrating Object & Collection Initializers. Basically, we got a List back as shown below -
var theWhiteHouseStaff = new List { new Monkey{ Name = "George W Bush", Age = 16}, new Monkey{ Name = "Donald Rumsfield", Age = 16}, new Monkey{ Name = "Condolezza Rice", Age = 16}, new Monkey{ Name = "Dick Cheney", Age = 16} } ;
It is notable that List implements IEnumerable, so the above is a queryable object. So, you could write a query, that looks like -
var q = from staff in theWhiteHouseStaff select new {staff.Name} ;
Practical Application: "var q" <-- Anonymous Type (+). An anonymous type that holds an Anonymous Type with one property "staff.Name". Also, "var" lets you create an Implicitly typed local variable (+) . This means, a) You didn't have to declare/write a class structure to hold a type with one property called "Name" of data type string. b) You don't have to maintain that either - you can change the structure of the above query, and "it just works" :)
Now, the above query, can also be written like this -
var q = from staff in theWhiteHouseStaff select new { Name = staff.Name } ;
Practical Application: "new { Name = staff.Name }" <-- Object Initializer (+). The anonymous type, is being initialized by an Object Initializer. The anonymous type doesn't have logic, or a constructor. But it does have public setters on it's properties, so there you go - the Object Initializer can now take advantage of those, and the query is slowly decomposing into plain vanilla C# 3.0.
The above query, further decomposes into the below -
var q = theWhiteHouseStaff.Select(staff => new {staff.Name}) ;
WHOAA !!!, lets look at this query once again, only color coded this time ;-)
var q = theWhiteHouseStaff.Select(staff => new {staff.Name}) ;
(PS: If the RSS Feed eats the color coding, I suggest you come see it on my blog)
Practical Application: The yellow var q, is an Anonymous Type (+) "q", the "var" lets you create an implicitly typed local variable (+). The theWhiteHouseStaff is an IEnumerable The green Select is an Extension Method (+). The Gray staff => new { staff.Name } is a Lambda expression (+) that is participating in type-inference (+). and the new {staff.Name} is an Object Initializer (+).
So, the LINQ Query
var q = from staff in theWhiteHouseStaff select new {staff.Name} ;
is *absolutely* the same as the C# 3.0 language construct -
var q = theWhiteHouseStaff.Select(staff => new {staff.Name}) ;
Thus, the (Linq) query expression has been translated (to plain vanilla C# 3.0). This is called as Query Expression Translation, and this is the reason behind C# 3.0 enhancements. :)Cool huh?

Labels: , , , ,

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home