CSharp/C# Tutorial - C# Lambda Expressions

A lambda expression is an unnamed method written in place of a delegate instance.

Given the following delegate type:

delegate int Converter (int i);

We could assign and invoke the lambda expression x => x * x as follows:

Converter sqr = x => x * x;
Console.WriteLine (sqr(3)); // 9

A lambda expression has the following form:

(parameters) => expression
We can omit the parentheses if and only if there is exactly one
parameter of an inferable type.

In our example, there is a single parameter, x, and the expression is x * x:

x => x * x;

Each parameter of the lambda expression corresponds to a delegate parameter, and the type of the expression corresponds to the return type of the delegate.

In the code above, x corresponds to parameter i, and the expression x * x corresponds to the return type int, therefore it is compatible with the Converter delegate which is listed as follows:

delegate int Converter (int i);

A lambda expression's code can be a statement block instead of an expression.

x => { return x * x; };

Lambda expressions are used most commonly with the Func and Action delegates.

We can rewrite the above code as follows:

Func<int,int> sqr = x => x * x;

Here's an example of an expression that accepts two parameters:

Func<string,string,int> totalLength = (s1, s2) => s1.Length + s2.Length;
int total = totalLength ("a", "the"); 

Capturing Outer Variables

A lambda expression can reference the local variables and parameters of the method where it's defined.

For example:

static void Main(){
   int factor = 2;
   Func<int, int> multiplier = n => n * factor;
   Console.WriteLine (multiplier (3)); // 6

Outer variables referenced by a lambda expression are called captured variables.

A lambda expression that captures variables is called a closure.

Captured variables are evaluated when the delegate is actually invoked, not when the variables were captured:

int factor = 2;
Func<int, int> multiplier = n => n * factor;
factor = 3;
Console.WriteLine (multiplier (3)); // 6

Lambda expressions can update captured variables:

int outerVariable = 0;
Func<int> myLambda = () => outerVariable++;
Console.WriteLine (myLambda()); // 0
Console.WriteLine (myLambda()); // 1
Console.WriteLine (outerVariable); // 2

Anonymous Methods

To write an anonymous method, include the delegate keyword followed optionally by a parameter declaration and then a method body.

For example, given this delegate:

delegate int Converter (int i);

We could write and call an anonymous method as follows:

Converter sqr = delegate (int x) {return x * x;};
Console.WriteLine (sqr(3)); // 9

The first line is semantically equivalent to the following lambda expression:

Converter sqr = (int x) => {return x * x;};

Or simply:

Converter sqr = x => x * x;

Anonymous methods capture outer variables in the same way lambda expressions do.