Published: 12 Mar 2007
By: Granville Barnett

Introducing LINQ is the first part of a series of articles on Language Integrated Query (LINQ). This series will cover the core essentials of LINQ and its use with other technologies like ASP.NET, Win Forms and WPF.

This and the forthcoming articles are designed to be a comprehensive tutorial on LINQ, having completed the series you will have a thorough understanding of LINQ and C# 3.0.

All code in the series will use the latest publicly available CTP at the time of writing.

Introducing LINQ Series

  • Part 1 In this part you will learn how to the query in-memory collections.
  • Part 2 In this part we will look at querying relational data.
  • Part 3 In this part we will look a little more at what entities are, as well as taking a closer look at the key types we can use and their application.
  • Part 4 In this part of the series we will use LINQ, ASP.NET and ASP.NET AJAX to replicate the to-do list that Scott Guthrie created a while back to show off the features of ASP.NET AJAX.
  • Part 5 In this part of the series I will explain the DataContext class in depth through a series of examples and explanations.
  • Introducing LINQ – Part 1

    In this article we will cover only the querying of in-memory collections, in future parts we will look at using LINQ with relational data (LINQ to SQL) and XML (LINQ to XML).

    This article has been designed to give you a core understanding of LINQ that we will rely heavily on in subsequent parts of this series.

    Before diving into the code it is essential to define what LINQ actually is. LINQ is not C# 3.0, and vice versa. LINQ relies heavily on the new language enhancements introduced in C# 3.0; however, LINQ essentially is the composition of many standard query operators that allow you to work with data in a more intuitive way regardless of the data source.

    The benefits of using LINQ are significant – queries are a first class citizen within the C# language, benefit from compile time checking of queries, and the ability to debug (step through) queries. We can expect the next Visual Studio IDE to take full advantage of these benefits – certainly the March 2007 CTP of Visual Studio Orcas does!

    In-Memory Collections

    The best way to teach new technologies is to just to show you an example and then explain what the heck is going on! – That will be my approach throughout this series; hopefully it is a wise decision.

    For our first example we will compose a query to retrieve all the items in a generic List collection (Fig. 1).

    Figure 1: Selecting all the items in a generic List collection

    The code example given in Fig. 1 is very basic and its functionality could have been replicated easier by simply enumerating through the items in the List via a foreach loop.

    In Fig.1 we compose a query that will return each of the items in the people List collection by aliasing the people collection with a variable p and then selecting p (p is of type string remember as the people List is a collection of immutable string objects).

    You may notice that query is of type IEnumerable<string> - this is because we know that query will hold an enumeration of type string. When we foreach through the query the GetEnumerator of query is invoked.

    At this time it is beneficial to look at exactly what the compiler generated code looks like (Fig. 2).

    Figure 2: Compiler generated code for Fig. 1

    Fig. 2 reveals that our query has actually been converted by the compiler to use an extension method (in this case just the Select extension method is used) taking a delegate as its argument.

    You will find that queries and lambda expressions are simply a facade that we deal with in order to make our lives easier – under the covers the compiler is generating the appropriate code using delegates. Be aware of this internal compiler behavior!

    Also be aware that a cached anonymous delegate method is generated at compile time as well (Fig. 3) – we will discuss this particular feature in future articles.

    Figure 3: Compiler generated cached anonymous delegate method

    We will now take a look at a more complex query of the same collection which retrieves a sequence of all strings in the List whose length is greater than 5(Fig. 4).

    Figure 4: A more complex query

    The example in Fig. 4 relies on the use of two other standard query operators – Where and orderby to achieve the desired results.

    If we examine the code generated by the compiler for the Example2 method you will see that shown in Fig. 5 – notice as well that we now have another two cached anonymous delegate methods (Fig. 6) – each of which having the type signature of their corresponding delegates (Where delegate and orderby delegate).

    Figure 5: Compiler generated code for Fig. 4

    Figure 6: Cached anonymous delegate methods for their respective Where and orderby delegates defined in Fig. 5

    The type signature of the Where delegate (Fig. 5) is Func. The delegate takes a string argument and returns a bool depending on whether the string was greater than 5 characters in length. Similarly the orderby delegate (Fig. 5) takes a string argument and returns a string.

    I encourage you to further explore the querying of collections – I have blogged extensively on the subject (http://gbarnett.org/archive/tags/LINQ/default.aspx).

    Standard Query Operators

    For completeness I will briefly cover what the standard query operators entail.

    When using LINQ with any supported data source (in-memory, relational data, XML) we can make use of a set of a standard query operators which empower us to manipulate our data source more effectively. A few standard query operators include:

    • Select
    • OrderBy
    • Where
    • SelectAll
    • TakeWhile
    • Take
    • Skip
    • First
    • SkipWhile
    • ...

    There are a tonne of standard query operators and I advise you to explore the use of each to gain a richer understanding of how to deal with data.

    We will cover many of the standard query operators in future parts of this series.

    Lambda Expressions

    Lambda expressions provide a clearer syntax for anonymous delegates – in this section we will replicate the code in Fig. 4 by using lambda expressions and extension methods (Fig. 6).

    Figure 6: Same example as Fig. 4 but using lambda expression and extension methods

    A lambda expression normally takes the form of arguments => expression, the expression is always preceded by the => token. If you want to have a lambda expression with more than one argument you must enclose the arguments in parentheses delimited by a comma.

    If you noticed in Figs 2 and 5 the compiler generated code actually uses extension methods not a query – this is purely an implementation detail, much like the use of lambda expressions in Fig. 6 will be converted to anonymous delegates by the compiler (Fig. 7).

    Figure 7: Compiler generated code for Fig. 6

    We will use lambda extensions extensively in future parts of this series.

    Summary

    In this article we looked at some examples of using LINQ with queries, and extension methods as well as looking at the compiler generated code.

    Please explore the standard query operator library and investigate the code generated by the compiler as the next wave of language compilers inject an awful lot of code behind the scenes that you will not be aware of unless you disassemble your code.

    Introducing LINQ Series

  • Part 1 In this part you will learn how to the query in-memory collections.
  • Part 2 In this part we will look at querying relational data.
  • Part 3 In this part we will look a little more at what entities are, as well as taking a closer look at the key types we can use and their application.
  • Part 4 In this part of the series we will use LINQ, ASP.NET and ASP.NET AJAX to replicate the to-do list that Scott Guthrie created a while back to show off the features of ASP.NET AJAX.
  • Part 5 In this part of the series I will explain the DataContext class in depth through a series of examples and explanations.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Granville Barnett

    Sorry, no bio is available

    This author has published 32 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    C# 4.0 Reflection Programming - Part 3
    In the previous article, we used the reflection to obtain the information of an assembly, module, ty...
    C# 4.0 Reflection Programming - Part 2
    As introduced in the first article, the most typically-used tools associated with .NET reflection ar...
    C# 4.0 Reflection Programming - Part 4
    In this last article of this series, we will learn what to do with reflection. But before making the...
    Understanding and Using Extension Methods
    Extension methods were new to C# 3.0. They allow you to add a method to an existing type without hav...
    Introduction to C# 3.0 features
    C# 3.0 introduced some of very useful features built on top of 2.0. This article explains the usage,...

    You might also be interested in the following related blog posts


    Oredev Wrap-Up read more
    Introducing SharePoint 2010 Training at U2U read more
    The Underground at PDC read more
    10 resources to learn Moq read more
    Building A Product For Real read more
    My History of Visual Studio (Part 6) read more
    BeginDialOut with Office Communicator Clients read more
    DotNetNuke Fusion Results for Q3 read more
    Dynamic in C# 4.0: Introducing the ExpandoObject read more
    GiveCamps Get a new Sponsor read more
    Top
     
     
     

    Discussion


    Subject Author Date
    placeholder Nice article my man! Andrew Siemer 11/5/2009 7:14 PM
    Nice Anil Pandey 2/8/2011 5:58 AM
    placeholder Nice article Shaiju Janardhanan 6/28/2013 4:26 AM
    Nice Intro Mo'taz Jamal 5/5/2007 4:53 PM
    placeholder LINQ Sunny Sunny 12/10/2008 12:04 PM

    Please login to rate or to leave a comment.