Understanding C# 3.0 Features (7) Query Expression

[LINQ via C# series]

This kind of code has been introduced again and again:

var positive = from number in source
               where number > 0
               orderby number descending
               select number.ToString(CultureInfo.InvariantCulture);

This is called the query expression syntactical sugar, providing a T-SQL-like way to write query in C#.

The first thing to clarify is, this query expression is not recommended and I never used it in my projects.

Syntax

Since this is not a recommended coding way, I just give a brief introduction. The following slide is from a presentation from Microsoft Technical Roadshow 2007:

understanding-csharp-3-features-query-expression

For the details you can take a look at the Query Expression Section of the C# Version 3.0 Specification.

Compilation

The only thing need to understabd is, the above query expression is compiled into normal method invocations:

IEnumerable<string> positive = source.Where(number => number > 0)
                                     .OrderByDescending(number => number)
                                     .Select(number => number.ToString(
                                            CultureInfo.InvariantCulture));

The Where(), OrderByDescending(), and Select() are all extension methods for IEnumerable<T> type defined in the .NET 3.5 FCL:

  • Since source is an integer array, and int[] implements IEnumerable<int>, so Where(), OrderByDescending() and Select() can also be invoked on int[]
  • Where() returns a IEnumerable<int>, so we can immediately invoke OrderByDescending() on the return value of Where()
  • For the same reason, we can fluently invoke Select()

This is called fluent interface pattern, which will be explained later.

This table shows some of the translation correspondings of the compilation:

Query expression Method invocation
where clauses Where()
orderby clause OrderBy(), OrderByDescending(), ThenBy(), ThenByDescending()
Select clause Select()
group clause GroupBy()
join clause Join()
Multiple generators SelectMany()

Details of those methods will be covered later.

Query expression vs. query method

The above 2 queries work totally the same, because the former is compiled into the latter. By roughly checking Framework Design Guidelines 2nd, I didn’t see comparison between query expression coding and normal method coding yet.

Personally, normal query methods (also called query operators in LINQ) are recommended, and I consistently use query methods in projects, instead of query expression. Here are the reasons:

  • Query expression will be compiled into normal method invocation, and writing exact method invocation code helps understanding what is happening, and gets developers less confused;
  • In some scenarios, query cannot be implemented by pure query expression, then query method has to come out; So for the consistency consideration, always using query method is preferred.

For the second reason, here is an example:

IQueryable<Product> results = (from product in source
                               where product.Category.CategoryName == "Beverages"
                               orderby product.ProductName
                               select product) // Query expression cannot do pagination.
                              .Skip(50) // So it has to be mixed with query methods.
                              .Take(10);

This looks some kind of consistency breaking. I prefer always query methods all over the project, because consistency is so prioritized.

Again, this comparison is from my personal perspective. One team’s coding conversion should fit its current members.

In the series, query methods are consistently used to explain LINQ. And query expressions will be discussed in the upcoming functional programming posts.

Published Wednesday, December 16, 2009 1:00 PM by Dixin

Comments

# re: Understanding C# 3.0 Features (7) Query Expression

Friday, May 28, 2010 8:42 AM by rajnepal

Can you please tell me why  query expression is not recommended?

Thanks

# re: Understanding C# 3.0 Features (7) Query Expression

Friday, May 28, 2010 12:11 PM by Dixin

As I said, this is a personal opinion.

First, I have used LINQ to Objects, LINQ to SQL, and PLINQ in several projects. I found that, at the beginning, usually query expression is quickly accepted by developers new to LINQ, because they think query expression is SQL-like. But later, they get in trouble with more complex query, especially those queries that cannot be done by just query expression.

Query methods can be helpful because they are closer to the actual code after compilation. And, everyone is familiar with method invocation, isn't it?

A second reasion is the consistency. I added a code sample in the last section.

Again, this is a personal experience from practical LINQ programming. Anyway, each dev team should make a coding convension that fits itself.

Leave a Comment

(required) 
(required) 
(optional)
(required)