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

Lambda expressions and expression trees sound mysterious but when you get to grips with them they are nothing but methods wrapped in a delegate. Find out how to use lambdas and how to generate them on the fly using expression trees.

There is a newer version of this article. See: 
Deep C# - Anonymous Methods, Lambdas And Closures

 

Banner

Lambda expressions

Lambda expressions sound esoteric; the name comes from lambda calculus, a branch of computer science not much visited these days.

In practice, however, lambda expressions are simply a more concise way of writing an anonymous method.

The basic syntax is:

(comma separated parameters)=>
{semicolon terminated statement list;}

The => symbol is read “becomes” to indicate that the parameters are transformed into the actions.

A lambda expression shares all its characteristics with anonymous methods.

For example, to define the Hello anonymous method listed earlier using a lambda expression you would write something like:

delegate int HelloType(int param);
HelloType HelloInst = (int param1) =>
{
MessageBox.Show("Hello delegate World"
 +param1.ToString());
return ++param1;
};

Once the lambda expression is encapsulated by the delegate instance everything works in the same way.

Notice that lambda expressions, like anonymous methods, “capture” the local variables in the same scope as themselves. That is they can make use of closure.

There are some tricks that you can use with lambda expressions to make the method definition even more concise and flexible.

The first is that the compiler can deduce the type of the parameters from the delegate type.

Essentially the lambda expression has to have the same number of parameters as the delegate and the return type, if any, has to be implicitly convertible to the return type of the delegate.

Thus the previous lambda expression can be written:

HelloType HelloInst = (param1) =>
{
MessageBox.Show("Hello delegate World"
  + param1.ToString());
return ++param1;
};

You can also leave out the brackets if the lambda has only one parameter and you can use empty brackets () if there are no parameters at all.

Standard delegates

Lambdas have made is much easier to use standard types of function within the .NET framework and to make it even easier there are a range of standard pre-defined delegate types.

The Action delegates provide a way to encapsulate a method that does something i.e. is an "action" returning void and anything from zero to 16 parameters. For example:

Action<int> HelloInst = (param1) =>
{
MessageBox.Show( Hello delegate World"
 + param1.ToString());
};

To use Action with additional parameters you simply keep specifying them up tot he maximum e.g.

Action<int><int><string> 
MyAction=(p1,p2,p3) => ...

The Func delegate works in the same way as the Action delegate but you can also specify a return type in addition to up to sixteen input parameters. The return type is specified as the final type. For example:

Func<int,int> HelloInst = (param1) =>
{
MessageBox.Show("Hello delegate World"
 + param1.ToString());
return ++param1;
};

Using Action or Func you can create a delegate that can encapsulate almost any lamdba expression but notice that there it might still be better to define your own delegate to convey the meaning of what the lambda is supposed to do.

The need to convey a meaning is the motivation behind there being a number of other standard predefined delegates as well as the Action and Func delegates.

For example, a predicate in mathematical logic is a function which evaluates to true or false i.e. a function returning a boolean. The Predicate<T> delegate can be used to wrap a lambda that accepts a single parameter and returns a boolean. That is Predicate <T> is identical to Func<T><bool>.

Similarly the Comparison<T> delegate takes two input parameters, x, y say,  of the same type and returns an int that indicates the relative "size" of the two objects - negative means x<y, zero means x=y and positive means x>y. For example

Comparison<int> Bigger(x,y)=> 
{
    if(x<y) return -1;
    if(x=y) return 0;
    return 1;
}

There is also a Converter<Tin,Tout> delegate which represents a method that converts the input type to the output type:

Convertor<int,string> MyConv (x,y)=>
{
return x.ToString();
}

There are lots of other predefined delegates but they rapidly become increasingly specilised like the EventHandler<TEventArgs> delegate.

Banner

<ASIN:1449380344>

<ASIN:0123745144>

<ASIN:0321658701>

<ASIN:0321741765>

<ASIN:0470495995>

<ASIN:0672330792>

<ASIN:0521114292>



Last Updated ( Tuesday, 20 September 2016 )