Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / C#

Understanding LINQ (C#)

Rate me:
Please Sign up or sign in to vote.
4.68/5 (100 votes)
12 Jun 2007CPOL6 min read 566.7K   8.4K   254  
An article describing the new language features of LINQ
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Understanding LINQ (C#)</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/styles/global.css" />
</head>
<body>

<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>
Title:       Understanding LINQ (C#)
Author:      Amro Khasawneh
Email:       amroamroamro@hotmail.com
Member ID:   3151565
Language:    C# 2.0, C# 3.0
Platform:    Windows, .NET 2.0, .NET 3.0, .NET 3.5
Technology:  .NET
Level:       Beginner
Description: An article describing the new language features of LINQ
Section      .NET Technology
SubSection   C#, C# 3.5, Orcas, LINQ
</pre>


<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       -->

<h2>Contents</h2>
<ul>
<li><a href="#Introduction">Introduction</a></li>
<li><a href="#NewLanguageFeatures">New Language Features</a></li>
	<ul>
	<li><a href="#AutomaticProperties0">Automatic Properties</a></li>
	<li><a href="#LocalVariableTypeInference1">Local Variable Type Inference</a></li>
	<li><a href="#ObjectInitializers2">Object Initializers &amp; Collection Initializers</a></li>
	<li><a href="#AnonymousTypes3">Anonymous Types</a></li>
	<li><a href="#LambdaExpressions4">Lambda Expressions</a></li>
	<li><a href="#ExtensionMethods5">Extension Methods</a></li>
	<li><a href="#QuerySyntax6">Query Syntax</a></li>
	</ul>
<li><a href="#FinalNotes">Final Notes</a></li>
<li><a href="#Resources">References &amp; Resources</a></li>
</ul>
<br />

<!-------------------------------     STEP 3      --------------------------->
<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   -->

<h2><a name="Introduction">Introduction</a></h2>
<p>This article is about LINQ which I think is one of the most exciting features in Orcas. LINQ makes the concept of querying a first-class programming concept in .NET. The data to be queried can take the form of XML (LINQ to XML), databases (LINQ-enabled ADO.NET: LINQ to SQL, LINQ to Dataset and LINQ to Entities) and objects (LINQ to Objects). LINQ is also highly extensible and allows you to build custom LINQ enabled data providers (e.g.: LINQ to Amazon, LINQ to NHibernate, LINQ to LDAP).</p>

<img src="UnderstandingLINQ.gif" style="" width="332" height="234" alt="LINQ Architecture (MSDN Magazine - June 2007)" />

<p>I will discuss some of the new language features and improvements that are introduced in C# 3.0, and it is those features that enable the full power of LINQ which makes it possible to write something like this:</p>

<pre lang="cs">
var result = from c in Customers
             where c.City == Boston"
             orderby c.LastName descending
             select new { c.FirstName, c.LastName, c.Address };
</pre>

<p>Remember that if you want to play around with LINQ or try the examples yourself, you will need to download <a href="http://msdn2.microsoft.com/en-us/vstudio/aa700831.aspx">Visual Studio Orcas Beta 1</a>.<br />In case you don't want to download the whole VS, you can check the <a href="http://www.microsoft.com/downloads/details.aspx?familyid=1e902c21-340c-4d13-9f04-70eb5e3dceea">LINQ Preview (May 2006 CTP)</a>
which runs on top of VS 2005 (there are a few changes in Beta 1 from the way
LINQ worked in the May CTP).</p>
<br />


<h2><a name="NewLanguageFeatures">New Language Features</a></h2>

<h3><a name="AutomaticProperties0">I/ Automatic Properties</a></h3>
<pre lang="cs">
public class Point {
    private int _x, _y;
    public int X {
        get { return _x; }
        set { _x = value; }
    }
    public int Y {
        get { return _y; }
        set { _y = value; }
    }
}
</pre>

<p>The above code simply defining a class with basic properties. Now with the new C# compiler in Orcas, we can write a shorter cleaner version using Automatic Properties which automatically generates the private fields with get/set operations :</p>

<pre lang="cs">
public class Point {
    public int X { get; set; }
    public int Y { get; set; }
}
</pre>

<p>The code above is even more readable and less verbose.<br />Note that this feature has nothing to do with LINQ, I just thought it would be appropriate to list it with the other new language features.</p>


<h3><a name="LocalVariableTypeInference1">II/ Local Variable Type Inference</a></h3>
<p>With this feature, the type of the local variable being declared is inferred from the expression used to initialize the variable. This is achieved using the <code>var</code> keyword (familiar to those who works with scripting language but actually is quite different). It allows us to write the following code:</p>

<pre lang="cs">
var num = 50;
var str = "simple string";
var obj = new myType();
var numbers = new int[] {1,2,3};
var dic = new Dictionary&lt;int,myType&gt;();
</pre>

<p>The compiler would generate the same IL as if we compiled:</p>

<pre lang="cs">
int num = 50;
string str = "simple string";
myType obj = new myType();
int[] numbers = new int[] {1,2,3};
Dictionary&lt;int,myType&gt; dic = new Dictionary&lt;int,myType&gt;();
</pre>

<p>Note that there is no un-typed variable reference nor late-binding happening, instead the compiler is inferring and declaring the type of the variable from the right-hand side of the assignment, thus the <code>var</code> keyword is generating a strongly typed variable reference.</p>


<h3><a name="ObjectInitializers2">III/ Object Initializers &amp; Collection Initializers</a></h3>
<p>Lets use the same <code>Point</code> class defined earlier, an suppose we want to define an instance of this class. We will have to create the object and start setting its properties, the code would look like this:</p>

<pre lang="cs">
Point p = new Point();
p.X = 0;
p.Y = 0;
</pre>

<p>This could be rewritten using Objects Initializers and combined into:</p>

<pre lang="cs">
Point p = new Point() { X = 0, Y = 0 };
</pre>

<p>This feature can also be used with collection. Take a look at this example:</p>

<pre lang="cs">
List&lt;Point&gt; points = new List&lt;Point&gt; {
    new Point { X = 2,  Y = 5 },
    new Point { X = 1, Y = -10 },
    new Point { X = 3, Y = 0 }
};
</pre>

<p>Note that the compiler will generate a long hand code equivalent to the above one. It makes calls to the <code>Add()</code> method to add elements to the collection one at a time.</p>


<h3><a name="AnonymousTypes3">IV/ Anonymous Types</a></h3>
<p>This language feature enable us to define inline types without having to explicitly define a class declaration for this type. In other words, imagine we want to use a <code>Point</code> object without defining the class <code>Point</code> (it would be anonymous). We will use the same object initializer syntax discussed earlier but without the type name:</p>

<pre lang="cs">
var p = new {X = 0, Y = 2};
</pre>

<p>Inside Orcas you will have full intellisense support. So when you use the variable <code>p</code> you will get a list of properties this anonymous type has.</p>


<h3><a name="LambdaExpressions4">V/ Lambda Expressions</a></h3>
<p>C# 2.0 introduced anonymous methods, which allow code blocks to be written "in-line" where delegate values are expected. While anonymous methods provide the power of functional programming languages, the syntax is rather verbose. Lambda expressions provide a more concise, functional syntax for writing anonymous methods. A lambda expression is written as a parameter list (can be implicitly typed), followed by the <code>=&gt;</code> token, followed by an expression or a statement block.</p>
<p>As an example lets define a delegate type <code>MyDeleg</code> as:</p>

<pre lang="cs">
delegate R MyDeleg&lt;A,R&gt;(A arg);
</pre>

<p>we can then write using anonymous methods:</p>

<pre lang="cs">
MyDeleg&lt;int,bool&gt; IsPositive = delegate(int num) {
                                   return num &gt; 0;
                               };
</pre>

<p>Or we can use the new lambda expressions to write:</p>

<pre lang="cs">
MyDeleg&lt;int,bool&gt; IsPositive = num =&gt; num &gt; 0;
</pre>


<h3><a name="ExtensionMethods5">VI/ Extension Methods</a></h3>
<p>Extension methods make it possible to extend existing types and constructed types with additional methods, without having to derive from it or recompile the original type. So instead of writing helper methods for objects they become part of that object itself.</p>
<p>As an example, suppose we want to check a string to see if it is a valid email address. We would do this by writing a function that takes a string as an argument and returns a true/false. With Extension Methods we can do the following:</p>

<pre lang="cs">
public static class MyExtensions {
    public static bool IsValidEmailAddress(this string s) {
        Regex regex = new Regex( @"^[w-.]+@([w-]+.)+[w-]{2,4}$" );
        return regex.IsMatch(s);
    }
}
</pre>

<p>We defined a <b>static</b> class with a <b>static</b> method containing the extension method. Note how the static method above has a <code>this</code> keyword before the first parameter argument of type <code>string</code>. This tells the compiler that this particular Extension Method should be added to objects of type <code>string</code>. And then we can call it from the string as a member function:</p>

<pre lang="cs">
using MyExtensions;

string email = Request.QueryString["email"];
if ( email.IsValidEmailAddress() ) {
    // ...
}
</pre>

<p>It is worth mentioning that LINQ syntax makes use of built-in Extension Methods (e.g.: <code>where()</code>, <code>orderby()</code>, <code>select()</code>, <code>sum()</code>, <code>average()</code> and many more) that reside in the new <code>System.Linq</code> namespace in Orcas and define standard query operators that can be used against relational databases, XML and any .NET objects that implement <code>IEnumerable&lt;T&gt;</code>.</p>


<h3><a name="QuerySyntax6">VII/ Query Syntax</a></h3>
<p>Query expressions provide a language integrated syntax for queries that is similar to relational and hierarchical query languages such as SQL and XQuery. It is a shorthand for writing queries using the LINQ query operators (i.e. <code>from...where...select</code>). Visual Studio provides full intellisense and compile-time checking support for query syntax.<br />
When the C# compiler encounters a query syntax expression it actually transforms it into into explicit method invocation code that uses Extension Methods and Lambda Expressions.</p>
<p>To explain this, let me give an example:</p>

<pre lang="cs">
var result = from c in Customers
             where c.City.StartsWith("B")
             orderby c.LastName
             select new { c.FirstName, c.LastName, c.Address };
</pre>

<p>The above code is equivalent to the following:</p>

<pre lang="cs">
var result = Customers.Where( c =&gt; c.City.StartsWith("B") )
                      .OrderBy( c =&gt; c.LastName  )
                      .Select( c =&gt; new { c.FirstName, c.LastName, c.Address } );
</pre>

<p>The advantage of using Query Syntax is that the code is easier and more readable.<br />Also note that a query expression begins with a <code>from</code> clause and ends with either a <code>select</code> or <code>group</code> clause.</p>
<br />


<h2><a name="FinalNotes">Final Notes</a></h2>
<p>Most of the language features introduced in C# v3.0 that we saw (such as variable type inference, object initializers, anonymous types and lambda expressions) are only <i>"compiler tricks"/"syntactic sugar"</i> that means that the IL the compiler generates is the same as the long code version, therefore they are independent from the framework (NetFX) and runtime (CLR). However, they do need some framework support and specifically the "green bits" (.NET Framework v3.5) <code>System.Core.dll</code> assembly. This is why extension methods which in fact works at compile time (syntactic sugar) still rely on <code>System.Runtime.CompilerServices.ExtensionAttribute</code> introduced in <code>System.Core.dll</code><br />
On the other hand, query expressions syntax is just a mapping to the extension methods implementations that resides in <code>System.Linq</code>, <code>System.Data.Linq</code> and <code>System.Xml.Linq</code> namespaces.
</p>

<img src="UnderstandingLINQ1.png" style="vertical-align: top;" width="432" height="113" alt="Figure 1" />
<img src="UnderstandingLINQ2.png" style="vertical-align: top;" width="512" height="179" alt="Figure 2" />
<br />


<h2><a name="Resources">References &amp; Resources</a></h2>
<ul>
<li><a href="http://weblogs.asp.net/scottgu/archive/2007/05/15/new-orcas-language-feature-anonymous-types.aspx">"New Orcas Language Feature" Series by Scott Guthrie</a>: Great series explaining LINQ</li>
<li><a href="http://www.danielmoth.com/Blog/2007/02/linq-resources.html">LINQ Resources</a>: Blog entries by Daniel Moth</li>
<li><a href="http://msdn.microsoft.com/msdnmag/issues/07/06/CSharp30/">MSDN Magazine (June 2007)</a>: An article on C# 3.0 and LINQ</li>
<li><a href="http://msdn2.microsoft.com/en-us/bb330936.aspx">Visual Studio Orcas Samples</a>: C#/VB LINQ Samples for Beta 1</li>
<li><a href="http://msdn2.microsoft.com/en-us/vcsharp/aa336745.aspx">Future Versions</a>: C# 3.0</li>
<li><a href="http://msdn2.microsoft.com/en-us/netframework/aa904594.aspx">The LINQ Project</a>: Home of the LINQ Project</li>
</ul>

<!-------------------------------    That's it!   --------------------------->

</body>
</html>

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions