Wednesday, July 2, 2008

Building blocks and Data sources of LINQ - Part 2

Building blocks and Data sources of LINQ - Part 2

In the previous post, I coverted two new C# 3.0 features namly Object initialization Expressions and Extension Methods. In this post, I will cover the concept of Lamda Expressions and Expression Trees.

3.Lamda Expressions

This feature simplifies coding delegates and anonymous methods. Lambda expressions allow us to write functions that can be passed as arguments to methods. All lambda expressions use the lambda operator =>, which is read as "goes to".

Lamda Expression can also optionally postpone code generation by creating an expression tree that allows further manipulation before code is actully generated, which happens at execution time.

For an example, we could create a simple Person class. Fetch the person records based start letter in LastName using Lamda Expression.

    public class Person

{

public string FirstName { get; set; }

public string LastName { get; set; }

public int Age { get; set; }

}



public class MyLamdaExpression

{

public List GetPeople(string startLetter)

{

var people = new List

{

new Person {FirstName = "Kannan", LastName = "Arjun", Age = 20},

new Person {FirstName = "Rangoli", LastName = "A", Age = 53},

new Person {FirstName = "Seema", LastName = "Sekar", Age = 15},

new Person {FirstName = "Satya", LastName = "Saravanan", Age = 16}

};



var results = people.Where(p => p.LastName.StartsWith(startLetter));

return (List) results;

}

}


If we call this mehtod like GetPeople("A"), this will return the follwoing outputs:

Arjun
A

For an another example, suppose we have an array with 10 digits in it, and you want to filter for all digits greater than 5. In this case, you can use the Where extension method, passing a lambda expression as an argument to the Where method:

int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

foreach (int i in source.Where(x => x > 5))
Console.WriteLine(i);

The advantage of lambda expressions is that they give you the ability to perform expression analysis using expression trees.

4.Expressions Trees

Expression trees are nothing but those which represent the query itself. It is very important to understand that lambda expressions are always directly compiled into IL code by the compiler, so a lambda expression is a representation of a unit of executable code, it is not a data structure. See the picture given below for an easy understands, LINQ can treat lambda expressions as data at run time. The type Expression represents an expression tree that can be evaluated and changed at run time. It is an in-memory hierarchical data representation where each tree node is part of the entire query expression.

There will be nodes representing the conditions, the left and right part of the expression, and so on.

For an example, consider the following very simple lambda expression:

Func<int,int,int> function = (a,b) => a + b;

The variable function points at raw executable code that knows how to add two numbers. The lambda expression shown in above is a short hand way of writing the following method:

public int function(int a, int b)
{
return a + b;
}

One can call either the method shown above, or the lambda expression like this:

int c = function(3, 5);

After the function is called, the variable c will be set equal to 3 + 5, which is 8.

class Program {
static void Main(string[] args) {
Expression<Func> expression = (a, b) => a + b;
Console.WriteLine(expression);
}
}

The delegate type Func shown above in the declaration found is declared for us in the System namespace:

public delegate TResult Func<t1,t2,result>(T1 arg1, T2 arg2);

This code looks complicated, but it is used here to help us declare the variable function, which is set equal to a very simple lambda expression that adds two numbers together. Even if you don't understand delegates and generic functions, it should still be clear that this is a way of declaring a variable that references executable code. In this case it points at very simple executable code.


If you are using the code shown above, set a breakpoint on the WriteLine statement and run the program. Hover your mouse under the variable expression you may seen the expression tree like this,

and ExpressionTreeVisualizer is the new visualization feature avilable in VS 2008.. It can be used to visualize an expression tree.

Translating Code into Data
In the previous section, you saw how to declare a variable that points at raw executable code. Expression trees are not executable code, they are a form of data structure. So how does one translate the raw code found in an expression into an expression tree? How does one translate code into data?

LINQ provides a simple syntax for translating code into a data structure called an expression tree. The first step is to add a using statement to introduce the Linq.Expressions namespace: using System.Linq.Expressions;

Now we can create an expression tree:

Expression<func> expression= (a,b) > a + b;

The identical lambda expression shown in the previous example is converted into an expression tree declared to be of type Expression. The identifier expression is not executable code; it is a data structure called an expression tree.

In the next post we will see the concept of Anonymous Types and Implicitly Typed Local Variables in details.

Happy programming!!!