Hooked on LINQ

Hooked on LINQ - Developers' Wiki
for .NET Language Integrated Query

Quick Search

Advanced Search »

Edit

Extension Method Query Syntax

The extension method format is simply where you cascade multiple extension methods together, each returning an IEnumerable result to allow the next extension method to flow on. A new language feature called Lambda Expressions allows us to pass delegates for evaluation and for projection (shaping the return result collection) depending on what that operator needs.

Microsoft have defined a whole set of extension methods (called the Standard Query Operators), and these extensions introduce methods to any type that implements IEnumerable to allow us to write query operations. Every collection type built into the .NET framework implements IEnumerable, so we can access these extension methods when querying any built-in collection type. There is nothing specifically startling about these extension methods, in fact you might be shocked at their individual simplicity, but when combined and cascaded together the full power of LINQ to Objects becomes most apparent. The basic extension method syntax takes the following general form -

[source collection].[extension method].[extension method]…;

For example -
[source].Where([Lambda Expression]).Select([Lambda Expression]);



The following standard query operators return an IEnumerable interface and can be cascaded into another Standard Query Operator extension method -

Cast, Concat, DefaultIfEmpty, Distinct, Empty, Except, GroupBy, GroupJoin, Intersect, Join, OfType, OrderBy, OrderByDescending, Range, Repeat, Reverse, Select, SelectMany, Skip, SkipWhile, Take, TakeWhile, ThenBy, ThenByDescending, ToArray, ToDictionary, ToList, ToLookup, ToSequence, Union, Where

Let us now look at some examples to see how we can cascade extension method operators to form queries. After seeing this syntax, especially the Join syntax, you will appreciate the Query Expression syntax even more.

List<Contacts> contacts = Contacts.SampleData();
 
var q = contacts.Where(c => c.State == "WA")
                .OrderBy(c => c.LastName)
                .ThenBy(c => c.FirstName);
 
foreach(Contacts c in q)
    Console.WriteLine("{0} {1}", c.FirstName, c.LastName);

Stewart Kagel
Chance Lard
Armando Valdes
Figure: Query gets all contacts in the state of "WA" ordered by last name, then first name

List<Contacts> contacts = Contacts.SampleData();
List<CallLog> callLog = CallLog.SampleData();
 
var q = callLog.Join( contacts, 
                      call => call.Number, 
                      contact => contact.Phone, 
                      (call, contact) => new { contact.FirstName, 
                                               contact.LastName, 
                                               call.When, 
                                               call.Duration })
               .Take(5)
               .OrderByDescending(call => call.When); 
        
foreach(var call in q)
    Console.WriteLine("{0} - {1} {2} ({3}min)",
        call.When.ToString("ddMMM HH:m"), 
        call.FirstName, call.LastName, call.Duration);

07Aug 11:15 - Stewart Kagel (4min)
07Aug 10:35 - Collin Zeeman (2min)
07Aug 10:5 - Mack Kamph (1min)
07Aug 09:23 - Ariel Hazelgrove (15min)
07Aug 08:12 - Barney Gottshall (2min)
Figure - Joins are particularly nasty in Extension Method syntax. Query returns the first 5 call details order by most-recent.

There are many other standard query operators that return a fixed result type, and cannot be cascaded together. These operators can be used in Query Expressions just like any of the others, it is just they end the IEnumerable chain and return a fixed result type.

Aggregate, All, Any, Average, Contains, Count, ElementAt, ElementAtOrDefault, EqualAll, First, FirstOrDefault, Fold, Last, LastOrDefault, LongCount, Max, Min, Single, SingleOrDefault, Sum

These operators can also be used in the select expression too; this mainly makes use of the aggregation operators like Count, Average, Min or Max.

Developer Tips – • Express the most limiting query method first; This reduces the workload of the successive operators;
• Split each operator onto a different line (including the period joiner). This allows you to comment out individual operators when debugging;
• Be consistent, within an application use the same style throughout;
• To make it easier to read queries, don’t be afraid to split up the query into multiple parts and indent to show hierarchy.

If you would like to comment on this page, click on the Discuss button located on the top-right of each page. Feel free to edit any mistakes or ommissions you find. If you have an objection or find in-appropriate content then contact the administrator. This website is not affiliated with Microsoft®, all content and opinions are those of the specific author and some advice, solutions and article may contain un-intentional errors - please use care. Powered by ScrewTurn Wiki version 2.0.33. Some of the icons created by FamFamFam.