Drop in the Bucket
One coder in the sea of s/w knowledge

LINQ Line by Line (Part 1): the from clause

Friday, August 17, 2007 6:36 PM

Straight to the Point

Integrated or not, what you are querying over has to come from somewhere. All LINQ queries (in C#) start with the from clause. The from clause consists of the two keywords from and in, an "iteration variable", and a "sequence"1. Here is a typical query expression; check out the from clause.

   1:    var query = 
   2:      from digit in number
   3:      select digit

The 'iteration variable' is 'digit' and the 'sequence' is 'number'. There are no unusual restrictions on the 'iteration variable'. The 'sequence' must support: IEnumerable (cool), IEnumerable<T> (cooler), or IQueryable<T> (way cool) -- all of which are derived from IEnumerable BTW.

A Little Deeper

Take this over simple example:

   1:    int number = 42;
   2:    
   3:    var query = 
   4:      from digit in number
   5:      select digit
   6:      
   7:    foreach(var d in query)
   8:    {
   9:      Console.WriteLine("A digit in number: {0}", d);
  10:    }

This won't compile. The message you get is, "Could not find an implementation of the query pattern for source type 'int'. 'Select' not found." Which is a slightly long winded way of saying, "the class is not enumerable". Change the code to the following (note the call to ToString):

   1:      int number = 42;
   2:   
   3:      var query =
   4:        from digit in number.ToString()
   5:        select digit;
   6:   
   7:      foreach (var d in query)
   8:      {
   9:          Console.WriteLine("A digit in number: {0}", d);
  10:      }

Strings are enumerable so the example works fine. The program prints '4' and '2' on their own lines.

Please Read On!

This tutorial introduced the from clause. We've only just begun. A lot is going on in this little program that makes performing a query possible and pleasant, that wasn't addressed (here). First the var keyword on line 3 allows us to use type inferencing. Type inferencing spares us from having to type the Type in front of the variable name. For an int or string, this is nice but not a killer feature. The actual name of the type of the query is: System.Linq.Enumerable+<selectiterator>d__d`2[System.Char,System.Char] (isn't it obvious). Which you couldn't even type in front of the variable name if you wanted to (anonymous type). Let's just leave it at: use var. The query expression itself isn't actually run until the foreach statement kicks in and starts asking for some digits. This is called "deferred execution".

Last, but not least, is the way that a string, which is an enumerable type, gets that 'Select' method. You might notice that the definition for IEnumerable hasn't changed since 2.0. So did the string class implement 'Select' just to support LINQ? Nope. A new technology called "extension methods" attaches an implementation of the 'Select' method and several other LINQ-isms to any class implementing IEnumerable. That's correct, a real live implementation was attached via an interface! It's similar to the idea of a mixin.

 

If you're interested these might get you started

In addition, look up the new IQueryable and IQueryProvider interfaces to see what those can give you. Dive in! This is a very deep pool.

Wrap it Up

The first statement in a C# query expression is the from clause. You provide it an iteration variable and some sort of sequence. It provides you with the source of your query. The next post in this series will take a look at the select clause.

Ref:

1. "C# Version 3.0 Specification", http://msdn2.microsoft.com/en-us/library/ms364047(vs.80).aspx


Tags: ,

Comments have been closed on this topic.