I love lambda expressions (part 2)!

In previous part we learned about lamda expressions, and ended up with the following example:

List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
Func<int, bool> funcNumbersSmallerThan25 = n => n < 25;

The delegate funcNumbersSmallerThan25 is compiled into executable code and can be called as follows:

List<int> numbersSmallerThan25 =
numbers.Where(funcNumbersSmallerThan25).ToList();

Expression trees

Now it’s time to introduce another feature called expression trees. An expression tree is a tree structure that contains lambda expressions. To demonstrate, let’s define the delegate as an expression using the following syntax:

Expression<Func<int, bool>> exprNumbersSmallerThan25 = n => n < 25;

Now the delegate exprNumbersSmallerThan25 is no longer compiled to executable code, but instead compiled as data. In order to use it, you have to compile it to IL first:

List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
Expression<Func<int, bool>> exprNumbersSmallerThan25 = n => n < 25;
var originalDelegate = exprNumbersSmallerThan25.Compile();
List<int> numbersSmallerThan25 = numbers.Where(originalDelegate).ToList();

If you call the ToString() method of the expression:

string lambda = exprNumbersSmallerThan25.ToString();

…you get back the lamda expression of the delegate:

Lambda expression

So what we did was create a delegate exprNumbersSmallerThan25  using the lambda expression ‘n => n < 25’, compiled it to IL code and used it. Instead of writing it using the lamba expression, you can also write it without the lamda expression:

List<int> numbers = new List<int> { 1, 7, 16, 23, 41, 66 };
ParameterExpression n = Expression.Parameter(typeof(int), "n");
Expression body = Expression.LessThan(n, Expression.Constant(25));
Expression<Func<int, bool>> exprNumbersSmallerThan25
= Expression.Lambda<Func<int, bool>>(body, n);
var originalDelegate = exprNumbersSmallerThan25.Compile();
List<int> numbersSmallerThan25 = numbers.Where(originalDelegate).ToList();

Actually this is exactly what internally is going on. Of course you would use lambda expressions because obviously it’s a more clear and shorter way to define an expression.

Expression tree viewer

To visualize expression trees, you can use the Expression Tree Visualizer tool that is part of the Visual Studio 2008 CSharp samples. To use it from Visual Studio, you have to build it first and copy the required DLL so that Visual Studio can use the visualizer:

  • First choose Help | Samples from the Visual Studio 2008 menu, click the ‘local Samples folder’ link and unzip the CSharpSamples/LinqSamples/ExpressionTreeVisualizer solution. 
  • Build the solution and then copy the bindebugExpressionTreeVisualizer.dll assembly to the ‘Visual Studio 2008Visualizers’ directory (to find out the directory on your system, select  Tools | Options | Projects and Solutions | General  from the Visual Studio menu)
  • Restart Visual Studio

You can now test the visualizer by debugging your test project, hovering your mouse above an expression variable and clicking the magnifying glass:

Expression magnifying glass

Click the magnifying glass to view the expression tree:

Expression Tree Viewer

Why use expression trees?

Expression trees provide an efficient data representation of lambda expressions (which are functions, ultimately) – so they are data structures that represent executable code. You can use them to interact with data at a low level: they can be evaluated, parsed and changed during runtime, and transformed to IL code. But why would we want to do such conversions?

To take an example, LINQ2SQL makes heavy use of expression trees. The following is a very simple example of a LINQ2SQL expression:

var employees = from e in db.Employees
where e.City == "Brussels"
select e;

What happens is that this expression is converted into an data structure (expression tree), and then this expression tree is analyzed by the LINQ compiler to decide the best way to convert it to SQL statements, which will be something like:

SELECT [t0].[City], [t0].[EmployeeName]
FROM [db0].[Employees] AS [t0]
WHERE [t0].[City] = @p0

So it’s nothing more than a transformation from expresssion -> data structure -> string representation. The goal of these transformation steps is to generate a data structure that is abstract, so that another process can handle it: the LINQ compiler can analyze and parse it in any way it wants (optimized for data access), or you can pass the same expression tree to some other piece of code that transforms it to something complete different, optimized for something else.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s