Lambda Expressions
Written by Administrator   
Wednesday, 02 June 2010
Article Index
Lambda Expressions
Expression Trees

Banner

Expression lambdas

A general lambda expression can have a mix of expressions and statements and is often refered to as a statement lambda. However there is a particularly simple form of the lambda that is very common.  An expression lambda" has only a single expression as its body and simply returns the result of the expression:

(parameters)=>expression

For example:

x => x*x;

is an expression lambda that takes x and squares it.

The one problem with expression lamdbas is that they can look more complicated than they are because they often make use of comparison operators. For example  the confusing looking:

x => x <= 10;

defines a lambda expression that returns true if x is smaller than or equal to 10 and false otherwise.

 

Notice that expresion lambdas are ideal for passing short chunks of code, Boolean conditionals for example, to other methods which is what they were designed for.

Expression lambdas are used extensively in the framework classes where there are a number of where the standard delegate types often make this easier. For example the Array type has a static Find method which accepts an array and a predicate and returns the first element that makes the predicate true.  For example

 

int i=
Array.Find<int>(MyIntArray, x => x>0);

returns the first element in MyIntArray that is positive.

Expression Trees

An expression lambda is also special because it can be convereted to an expression tree.

What is an expression tree?

Put simply an expression tree is just an object which contains all of the information contained in the lambda. It is a represenation of the function in data.

Why would you want to create an expression tree?

An expression tree can be stored or transmitted to another system where it can be implemented at a later time or remotely. You can think of an expression trees as a data exchange format for lambdas but they also allow you to create lambdas dynamically. You can create an expression tree without using a lambda and then use it to create the method that corresponds to the lambda. That is the expression tree is one way of dynamically generating a method.

The main reason that expression trees were introduced was so that LINQ which makes heavy use of expression lambdas could turn a query into a data structure and send this "over the wire" to a remote server but there are no doubt lots of alternative and inovative uses just waiting to be discovered.

To see expression trees in action lets take a simple expression lambda and convert it into an Expression object. When an expression lambda is assigned to an Expression varible it is automatically converted to an expression tree. For example:

Expression<Func<int, int>> 
ExTree = (x) => x * x;

Notice that you have to spefiy the delegate type that the Expression object is going to represent - in this case Func<int,int>. Following this instrcution ExTree contains a data represenation of the expression lambda. 

You can explore the expression tree using its methods and properties. For example:

Console.WriteLine(ExTree.Body);
Console.WriteLine(ExTree.Parameters[0]);
Console.WriteLine(ExTree.ReturnType);

results in

(x * x)
x
System.Int32

You can apply the method in an expression tree using the Compile method. For example:

Func<int, int> MyNewDelegate = 
ExTree.Compile();
int result=MyNewDelegate(3);

stores the expression lambda in MyNewDelegate and then uses it. You can also create the delegate on the fly:

int result= ExTree.Compile()(3)

An expression tree from scratch

Now that we have taken a expression lambda and converted it to an expression tree and then taken the expression tree and converted it back to the lambda all that is left is to build the expression tree from scratch. If you think about how complex a method can be you can see that this is an equally complex topic. Most of the methods that you need to generate an expression tree from scratch are provided by the Expression static class and its methods.

As a simple example of how this all works, let's create the squaring lambda from scratch. First we need to define the parameter:

ParameterExpression param = 
Expression.Parameter(
typeof(int), "x");

The parameter name "x" is only used in debugging and system messages. Next we need to define the body of the lambda and this is where things can get complicated:

Expression square = 
Expression.Multiply(param, param);

The Multiply method takes a lefthand side expression and a righthind side expression and multiplies them together. In this case we simply multiply the parameter by itself.

Now we can buld the expression tree:

Expression<Func<int,int>> ExTree = 
Expression.Lambda<Func<int,int>>(
square,param);

There are a number of different ways of creating an expression tree but the Lambda method simply takes the body and parameter and puts them together using the specified delegate type to define the type of the lambda.

Following this we can use the expression tree as if it had been derived from a lambda in the first place. For example:

Func<int, int> MyNewDelegate = 
ExTree2.Compile();
Console.WriteLine(
MyNewDelegate(3).ToString());

will display 9.

The most important point to understand is that you can build an expression tree that corresponds to a multiline method in this way. That is you can only automatically convert a single line expression lambda to an expression tree but you can build much more complex expression trees using the Expression static methods.

Lambda expression and expression trees are used extensively by LINQ but they are a facilities that have much more general uses.

Banner


Deep C# - Casting the Escape from Strong Typing

Casting is one of the most confusing aspects of any modern language and it often makes beginners think hard. But if you know why you are doing it, then the how makes a lot more sense. We have encounte [ ... ]



Deep C# - Interface

Interfaces - what are they for? Not quite inheritance yet they seem to fit the same purpose. Find out in this extract from my new book, Deep C#: Dive Into Modern C#.


Other Articles

<ASIN:1430229799>

<ASIN:0262201755>

<ASIN:0596800959>

<ASIN:047043452X>

<ASIN:193435645X>

<ASIN:0596007124>



Last Updated ( Tuesday, 20 September 2016 )