Introduce DataBase,Asp.net,JavaScript,Xml,Html,Css,Sql,Php,ASP.NET Controls,AJAX,Tools,HTML,CSS,JavaScript,Open Source Project,WPF,.Net Framework,Linq
Top Recommended Hosting

Lamda Expression in C#

by the3factory 3/10/2008 6:19:00 PM

Lamda expressions are inline delegates introduced with C # 3.0 language. It’s a concise way to represent anonymous method. It provides syntax to create and invoke functions. Although lamda expressions are simpler to use than anonymous methods, they do slightly differ on how they are implemented. Both anonymous methods and lamda expressions allow you define the method implementation inline, however, anonymous method explicitly requires you to define the parameter types and the return type for a method. Lamda expression uses the type inference feature of C# 3.0 which allows the compiler to infer the type of the variable based on the context.

Lamda expression can be broken down into parameters followed by execution code. e.g:

Parameter => executioncode.

The left hand side represents zero or more parameters followed by the lambda symbol => which is used to seprate the declartion of a parameter from the implementation of the method. Lambda expression is then followed by statement body.

Lamda expression allows us to pass functions as arguments to a method call. I will start with a simple example of lambda expression which returns even numbers from a list of integers.

//simple example of lambda expression.
public static void SimpleLambdExpression()
{
List<int> numbers = new List<int>{1,2,3,4,5,6,7};
var evens = numbers.FindAll(n => n % 2 == 0);
var evens2 = numbers.FindAll((int n) => { return n % 2 == 0; });
ObjectDumper.Write(evens);
ObjectDumper.Write(evens2);
}

Looking at the first lambda expression assigned to the evens variable, you will notice few things that are different from anonymous methods. First, we are not using delegate keyword anywhere in our code. Second, we are not defining the parameter and return types because the compiler infers the type based on context. The types in the expression are determined by the delegate definition. So in this case return type specified by the FindAll method takes a delegate which takes an int parameter and returns boolean. Lambda expression without braces and return type, provides the most concise way to represent anonymous methods. If the number of parameters is one then you can omit the parentheses surrounding the parameter as demonstrated in the first lambda expression. Although lamdba expression does not require explicit parameters, you have the option to define the parameters, braces and return type as shown in the second lambda expression assigned to the even2 variable. Notice that we are using the explicit parameter of int and also use the return type as we usually specify in a method. The return statement would not work if you do not enclose the execution code with parentheses considering that you are fully qualifying everything that attributes a method.

Another place where parentheses are required in lambda expressions is when you want to use a parameter in multiple blocks of code inside the lambda expression such as follows.

delegate void WriteMultipleStatements(int i);
public static void MultipleStatementsInLamdas()
{
WriteMultipleStatements write = i =>
{
Console.WriteLine("Number " + i.ToString());
Console.WriteLine("Number " + i.ToString());
};
write(1);
}

image001.png

In the above code sample, we have enclosed our code in curly brackets so that we can use the parameter in both the expressions. If there was no curly brackets, the compiler wouldn’t be able to recognize the variable i.

You can use lambdas expressions where a delegate may not have any parameter. In that case you have to supply a pair of empty parentheses to signify a method with no parameter. Here is a simple example which illustrates a lambda with no parameter.

delegate void LambdasNoParams();
public static void LambdasWithNoParameter()
{
LambdasNoParams noparams = () => Console.WriteLine("hello");
noparams();
}

image002.png

C# 3.0 defines the number of generic delegates that you can assign to your lambda expression instead of var keyword which infers the type. Lets take look at an example of using a few of those generic delegates.

public static void GenericDelegates()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
Func<int, bool> where = n => n < 6;
Func<int, int> select = n => n;
Func<int, string> orderby = n =>  n % 2 == 0 ? "even" : "odd";
var nums = numbers.Where(where).OrderBy(orderby).Select(select);
ObjectDumper.Write(nums);
}

In the above example we are using three different extension methods: where, orderby and select. The where extension method takes a generic delegate with int parameter and a return type of boolean to identity if a certain element be included in the output sequence. The select extension method takes an integer parameter and returns an integer, but it could return anything that you want the result to be transformed into — before being sent to the output sequence. In the orderby extension method we are taking the integer parameter and using it to identify if it is an even or odd. Based on that we sort the results. It would have been extremely cumbersome if we had to define three different delegates for each of these lambda expressions. With the introdution of Generic delegates in C# 3.0, it is fairly non trivial to assign our lambda expressions to generic delegates and pass those delegates to the extension methods. Generic delegates come in pretty handy and help you avoid writing common delegates which was common in .NET 1.1 and .NET 2.0 (since there were no generic delegates that came out of the box). Generic delegates allows you to define up to 4 parameters and 1 return type so you can have a delegate that may look something like this:

Func<int, bool, string, double, decimal> test;

If your method or delegates does not meet the criteria then you have to manually declare a delegate that takes those parameters. Generic delegates usually covers majority of scenarios but in cases wher it does not meet your need, feel free to write a custom delegate.

There are cases where type inferance may not return the data type that you really want the lambda expression to return. In those cases we can explicitly specify the parameter type on the lambda expression. For e.g:

Func<double, int> expr = (x) => x / 2;

The above expression returns a compiler error because by dividing a double, the infered type is actually going to be double. However, you are assigning the lambda expression to a delegate that has a return type of int. If int is what you really want to return from the method then you are better off casting the expression body to int to indicate your intent as shown below:

Func<double, int> expr = (x) => (int)x / 2;

Lambda expressions are basically of two types. One which is considered a simple expression where everything is infered and consist of an expression only. Second type of lambda expression is statement blocks which is composed of braces and return type. Let's write a lambda expression in both forms to see the difference.

//example showing two types of lambda expressions
public static void ExplicitParametersInLambdaExpression()
{
Func<int, int> square = x => x * x;
Func<int, int> square1 = (x) => { return x * x; };
Expression<Func<int, int>> squareexpr = x => x * x;
Expression<Func<int, int>> square2 = (int x) => { return x * x; }; //does not compile.
}

Let's go ahead and dissect each lambda expression one at a time. The first lambda expression is considered a simple expression which does not have a statement body because there is no return statement and braces whereas the second labmda statement includes a statement body because it has a return statement and braces. Although both get compiled to a delegate the benefit of lambda expressions without a statement body is that it can be converted to an expression tree which a certain provider can use to generate its own implementation. Much like LINQ to SQL will convert the expression tree to its domain specific language called SQL, and send it to the database. The third lambda expression is really where lambda expression shies from anonymous method. The beauty of this statement is the fact you can easily convert to an expression where as anonymous methods can only be converted to delegates. What is also great is that an expression can be converted back to a delegate by compiling the expression to delegate with the following syntax.

Func<int,int> sq = squareexpr.Compile();

The last lambda expression raises an exception because the compiler cannot convert a lamba expression that contains a statement body, as you can observe from the fact that it is surrounded by braces and a return statement.

Although you can use lamba expessions to generate expression trees, there is nothing preventing you from directly creating your own expression tree. Let’s walk through an example of creating an expression tree for a lambda expression square = x => x * x

//example creates expression tree of x *x
public static void CreatingExpressionTree()
{
ParameterExpression parameter1 = Expression.Parameter(typeof(int), "x");
BinaryExpression multiply = Expression.Multiply(parameter1, parameter1);
Expression<Func<int, int>> square = Expression.Lambda<Func<int, int>>(
multiply, parameter1);
Func<int, int> lambda = square.Compile();
Console.WriteLine(lambda(5));
}

You first start off with a parameter expression of type int.

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

The next step is to build the body of lambda expressions which happens to be a binary expression. The body consists of a multiply operator to the same parameter expression.

BinaryExpression multiply = Expression.Multiply(parameter1, parameter1);

The final step is to build the lambda expression which combines the body with the parameter as follows:

Expression<Func<int, int>> square = Expression.Lambda<Func<int, int>>(multiply,
parameter1);

The last step converts the expression to delegate and executes the delegate as follows:

Func<int, int> lambda = square.Compile();
Console.WriteLine(lambda(5));

Creating An Expression from Another Expression

You can take an expression tree and modify it to create another expression from it. In the following example we will start off with a lambda expression of x *x and then modify this expression to add 2 to it. Let’s have a look at an example.

public static void CreatingAnExpressionFromAnotherExpression()
{
Expression<Func<int, int>> square = x => x * x;
BinaryExpression squareplus2 = Expression.Add(square.Body,
Expression.Constant(2));
Expression<Func<int, int>> expr = Expression.Lambda<Func<int, int>>(squareplus2,
square.Parameters);
Func<int, int> compile = expr.Compile();
Console.WriteLine(compile(10));
}

We start off with a lambda expression which returns a sqaure.

Expression<Func<int, int>> square = x => x * x;

Next we generate body of the new lambda expression by using the body of the first lambda expression and adding constant of 2 to it and assigning it to the binary expression.

BinaryExpression squareplus2 = Expression.Add(square.Body, Expression.Constant(2));

In the last step we geneate the new lambda expression by combining the body with the parameters from the first labmda expression. The important point which I discovered in the below statement is that, a parameter's reference needs to be exactly the same from the first lambda expression which is square.Parameters. You cannot create a new instance of parameters collection which results in a runtime error.

Expression<Func<int, int>> expr = Expression.Lambda<Func<int, int>>(squareplus2,
square.Parameters);

Closures and Lambda Expressions

Closure is a concept that comes from functional programming. It essentially captures or uses the variable which is outside the scope of the lambda expression. What it essentially means is you can use variables inside the lambda expression that are declared outside of the scope of the lambda expression — you are able to use and capture the variable that is outside of the scope of the lambda expression. This has its advantages but could lead to issues as well since the outside context has the ability to change the variable value. Let’s drill through of an example of lambda expression in the context of closure.

public static void LambdaWithClosure()
{
int mulitplyby = 2;
Func<int, int> operation = x => x * mulitplyby;
Console.WriteLine(operation(2));
}

In the above example we are using the mulitplyby variable inside the lambda expression although it is declared outside the scope of the expression. This concept is called variable capture. In the background, C# compiler takes all those captured variables and puts them in a generated class. When you are using lambda expressions with outside variables, they are not picked up by the garbage collector, and are forced to hang around until they are used by the lambda expressions and the expression goes out of scope.

There are certain restrictions when you are using a lambda expression with a parameter with ref and out keyword. When your variable is passed with ref or out keyword, you must explicitly specify the parameter type because the compiler cannot infer the type of the variable. As shown in the example below.

delegate void OutParameter(out int i);
delegate void RefParameter(ref int i);
public static void GotchasWithLambdas()
{
//example with out parameter int i;
OutParameter something = (out int x) => x = 5;
something(out i);
Console.WriteLine(i);
//example with ref parameter.
int a = 2;
RefParameter test = (ref int x) => x++;
test(ref a);
Console.WriteLine(a);
}

Notice in the above code, I am explicitly specifying the parameter type of int in both cases, ref and out. If I omit the parameter type, the compiler will raise an error.

Another restriction that I have come across using lambdas is you cannot use params keyword in the parameter type for a lambda expression regardless of whether or not you expclicitly specify the type of the parameter. The following code does not compile because the parameter definition is attributed with params keyword.

delegate void ParmsParameter(params int[] ints);
public static void LambdaWithParam()
{
ParmsParameter par = (params int[] ints) =>
{
foreach (int i in ints)
{
Console.WriteLine(i);
}
};
}

In this article I introduced the syntax of a lambda expression — how it replaces anonymous methods. We also talked about how lambda expressions differ from anonymous methods because of the type inference, and its ability to be easily tranformed into delegates or expression trees. We learned the parameter restrictions of lambda expressions and how to write an expression from scratch and compile it to a delegate and vice versa.

Related posts

Sign up for PayPal and start accepting credit card payments instantly.


Powered by BlogEngine.NET 1.2.0.0