Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

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 | 9 comments | 11855 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 Types
c) Demystifying C# 3.0 - Part 3: Extension Methods
d) Demystifying C# 3.0 - Part 4: Lambda Expressions
e) 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<Monkey> back as shown below -

var theWhiteHouseStaff =
    new List<Monkey>
    {
        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<T> implements IEnumerable<T>, 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<T>
   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?

 

On 9/4/2006 1:48:07 AM Maulikk said ..
var q =
from staff in theWhiteHouseStaff
select new {staff.Name} ; In the above snippet how does the "staff" gets populated with the values?? what is the type of staff and why? Thanks in advance
Maulik

On 9/4/2006 6:25:49 AM Augustin Prasanna said ..
The way in which you explain in fantastic. good one.

On 9/4/2006 3:26:07 PM Sahil Malik said ..
Maulikk - excellent Q. C# 3.0 (oh heck C# vNext - thanks to .NET 3.0/WinFX Confusion) - does a lot of stuff under the scenes. You don't have to explicitly populate "staff" - it is there for you, for the query. Basically makes our life simple. It's an anonymous type.

On 9/4/2006 3:28:31 PM Sahil Malik said ..
Thanks Augustin - y'know it used to be even better, until people started getting offended by my weird sense of crass humor. :)

On 4/10/2007 8:08:15 AM mike123 said ..
Awesome articles and great way of explaining!!!

On 4/10/2007 9:16:00 AM Sahil Malik said ..
Thanks Mike123 :)

On 1/17/2008 6:33:27 AM Ajay said ..
I thoroughly enjoyed reading your articles. Very informative indeed. Do you have any more on this series or related? Is it possible to use LINQ queries on XML documents? I am looking at using XML's in a c# Silverlight application.

On 8/28/2008 11:04:01 AM Anton said ..
If only you could use LINQ to:
theWhiteHouseStaff.Remove("George W Bush");
theWhiteHouseStaff.Submit();

On 9/5/2008 2:36:28 PM Kaushik said ..
can u please explain this :
//CODE 1
public static T? Select<T>(this T? x, Func<T, T> selector)
where T : struct {
return x.HasValue ? new T?(selector(x.Value)) : null;
} //CODE 2
public static double? Abs(double? x) {
return from d in x select Math.Abs(d);
} 1) How does the 'select' of code 2 calles 'Select' of code 1 (Case sensitivity)
2) How does 'd' in code 2 is infered as double and not double? ; since its part of x which is double?
3) how do i get this from select clause working ...since x is not a collection.

Please post your comments:


Your feedback will be submitted for moderation, and will appear after it is approved.

Name:  
Email (optional): Your email address will not be posted.
URL (optional):
Comments: HTML will be ignored, URLs will be converted to hyperlinks  
Enter the text you see in the box:
 

Site designed and maintained by Sahil Malik | All Rights Reserved. ©2007 WinSmarts.com.