Lambda Expressions in C#

C# 3.0 introduces a new feature called lambda expressions. While this is not a revolutionary thing, it opens up a plethora of new possibilities for .Net programming. This post aims to introduce lambda expressions by providing a backgrounder, looking into its syntax and providing examples along the way.

A Little Bit of History

With the release of C# 2.0, came anonymous methods. For those of you who don’t know it, anonymous methods allow developers to write a block of code in places where a delegate is expected. Prior to this, developers are required to explicitly declare methods and attach them to delegates.  

To give you a clearer picture, here’s how one will write a very simple add delegate in pre-2.0 C#.

// EXAMPLE 1

delegate int BinaryExpression( int x, int y);
static int addFunction(int x, int y)
{
    return x + y;
}

static void Main(string[] args)
{

    BinaryExpression add = new BinaryExpression( addFunction );

    Console.WriteLine( add(4, 2) );
}

With anonymous methods you can easily bind the body of addFunction to a named delegate

// EXAMPLE 2
delegate int BinaryExpression( int x, int y);
static void Main(string[] args)
{
    BinaryExpression add = delegate(int x,int y)
                           {
                               return x + y;
                           };
    Console.WriteLine( add(4, 2) );
}

Lambda expressions offer an even more clever alternative to this. Just look at the example below.

// EXAMPLE 3
delegate int BinaryExpression( int x, int y);
static void Main(string[] args)
{
    BinaryExpression add = (x, y) => x + y;
    Console.WriteLine( add(4, 2) );
}

Before Anything Else…

Let’s take a look at the lambda expression syntax:

It follows the form (parameter-list) => expression; where expression can be any C# expression or a block of code. Just like anonymous methods you can use a lambda expression in place of a delegate. Below are some sample lambda expressions and their corresponding delegates. 

// assigns to void D(User u)
// Explicitly typed parameter
(User u) => Console.WriteLine(u.Username.ToUpper())

// assigns to bool D(User u)
// Implicitly typed parameter
(u) => u.Username == “User1”

// assigns to int D(int x, int y)
// Explicitly typed parameter
(int x, int y) => x + y

// assigns to int D(int x, int y)
// Implicitly typed parameter
// Uses a block instead of an expression
(x, y) => { return x + y; }

As you see from the above example, lambda expressions provide a little bit of magic in that it can infer the parameter type from the signature of the delegate it is assigned to.

Func’dafied

You might be thinking by now “WTF! I still have to declare those delegates?”. Well, not really. Lucky for us C# 3.0 provides a set of generic delegates at our disposal. Enter the Func delegate type in its different forms.

public delegate RT Func<RT>();
public delegate RT Func<T0, RT>(T0 a0);
public delegate RT Func<T0, T1, RT>(T0 a0, T1 a1);
public delegate RT Func<T0, T1, T2, RT>(T0 a0, T1 a1, T2 a2);
public delegate RT Func<T0, T1, T2, T3, RT>(T0 a0, T1 a1, T2 a2, T3 a3);


The only thing you need to remember here is that the last generic parameter is the return value.

So going back to example 3, we can now write it as.

// EXAMPLE 3.1
static void Main(string[] args)
{
    Func<int,int,int> add = (x, y) => x + y;
    Console.WriteLine( add(4, 2) );
}

Of course there will be times when this set of Func’s won’t satisfy your need. Like when you need a delegate signature that has more than 3 parameters or takes a ref or out as an argument. This is when you need to manually create a delegate type.

Resources

C# 3.0 Specification - http://download.microsoft.com/download/9/5/0/9503e33e-fde6-4aed-b5d0-ffe749822f1b/csharp%203.0%20specification.doc

Linq May 2006 CTP - http://www.microsoft.com/downloads/details.aspx?familyid=1e902c21-340c-4d13-9f04-70eb5e3dceea&displaylang=en

Linq/C# 3.0 Learning Guide - http://www.theserverside.net/tt/articles/showarticle.tss?id=CsharpLINQLearningGuide2007

Comments

# keithrull said:

Great detailed example and explanation jake! I wish i had this feature in .NET 1.0..

Monday, March 26, 2007 9:58 AM
# Keith Rull said:

A few days ago we helped Rolvin sort the list of girls he wants to date .. this time we'll help him find

Monday, March 26, 2007 4:44 PM
# jakelite said:

Many of us may not have noticed it but C# 2.0 gave us several really cool delegates and methods aimed at providing a gentle transition to the functional programming concepts introduced in C# 3.0 and Linq...

Thursday, March 29, 2007 8:03 AM
# Phil Yalden said:

At last, thanks to your article the penny has dropped. Now I understanding where LINQ and Lambda expressions are coming from

Wednesday, May 02, 2007 6:53 AM
# jakelite said:

Keith posted a great article demonstrating Linqs capabilities. There he was asked if his examples where

Tuesday, December 18, 2007 12:32 PM
# Keith Rull said:

I know. I know. I know. I wasn&#39;t able to post anything this past few weeks. It&#39;s been really

Friday, February 22, 2008 10:05 AM
# jakelite said:

Keith posted a great article demonstrating Linqs capabilities. There he was asked if his examples where

Wednesday, July 23, 2008 8:21 PM

Leave a Comment

(required) 
(required) 
(optional)
(required) 

Enter the numbers above: