Welcome to MSDN Blogs Sign in | Join | Help
Lambda Expressions

[Table of Contents]  [Next Topic]

In order to learn functional programming and a more declarative style of writing code, we need first to cover some basic material.  One of the first concepts is that of lambda expressions.  Lambda expressions can be summarized in one sentence:

Lambda expressions are simply functions/methods.

They have a different syntax, primarily so that they can be written in expression context (more on this shortly) instead of as a member of a class.  However, that is all they are.  For instance, the following lambda expression:

c => c + 1

 

is a function that takes one argument, c, and returns the value c + 1.

Actually, they are slightly more complicated than this, but not much more.  For the purposes of this tutorial, you only use lambda expressions when calling a method that takes a delegate as a parameter.  Instead of writing a method, creating a delegate from the method, and passing the delegate to the method as a parameter, you can simply write a lambda expression in-line as a parameter to the method.

To show lambda expressions in context, consider the problem where you have an array with 10 digits in it, and you want to filter for all digits greater than 5.  In this case, you can use the Where extension method, passing a lambda expression as an argument to the Where method:

int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

 

foreach (int i in source.Where(x => x > 5))

    Console.WriteLine(i);

 

To understand the semantics of this code, you needn't find some method elsewhere in the source code that does the selection; the code that you need to read is much tighter and smaller.  It reflects your intent in a much cleaner fashion.

Later on in this tutorial, you'll see a number of uses of the standard query operators.  Many of the standard query operators, including Where, take delegates as an argument, so this means that we can call them passing a lambda as an argument.

First, a quick review of delegates:

Defining, Creating, and Using a Delegate

In C#, a delegate is a data structure that refers to either a static method, or an object and an instance method of its class.  When you initialize a delegate, you initialize it with either a static method, or a class instance and an instance method.

The following code shows the definition of a delegate and a method that can be used to initialize the delegate:

// Defines a delegate that takes an int and returns an int

public delegate int ChangeInt(int x);

 

// Define a method to which the delegate can point

static public int DoubleIt(int x)

{

    return x * 2;

}

 

Now, you can create and initialize an instance of the delegate, and then call it:

ChangeInt myDelegate = new ChangeInt(DelegateSample.DoubleIt);

Console.WriteLine("{0}", myDelegate(5));

 

This, as you would expect, writes 10 to the console.

Using an Anonymous Method

With C# 2.0, anonymous methods allow you to write a method and initialize a delegate in place:

ChangeInt myDelegate = new ChangeInt(

    delegate(int x)

    {

        return x * 2;

    }

);

Console.WriteLine("{0}", myDelegate(5));

 

Using a Lambda Expression

With Lambda expressions, the syntax gets even terser:

ChangeInt myDelegate = x => x * 2;

Console.WriteLine("{0}", myDelegate(5));

 

This lambda expression is an anonymous method that takes one argument x, and returns x * 2.  In this case, the type of x and the type that the lambda returns are inferred from the type of the delegate to which the lambda is assigned.

If you wanted to, you could have specified the type of the argument, as follows:

ChangeInt myDelegate = (int x) => x * 2;

Console.WriteLine("{0}", myDelegate(5));

 

Using a Lambda with Two Arguments

When using the Standard Query Operators, on occasion, you need to write a lambda expression that takes two arguments.

If you have a delegate that takes two arguments:

// Defines a delegate that takes two ints and returns an int

public delegate int MultiplyInts(int arg, int arg2);

 

You can declare and initialize a delegate:

MultiplyInts myDelegate = (a, b) => a * b;

Console.WriteLine("{0}", myDelegate(5, 2));

 

Statement Lambda Expressions

You can write a more complicated lambda expression using statements, enclosing the statements in braces.  If you use this syntax, you must use the return statement, unless the lambda returns void:

int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 };

 

foreach (int i in source.Where(

        x =>

        {

            if (x <= 3)

                return true;

            else if (x >= 7)

                return true;

            return false;

        }

    ))

    Console.WriteLine(i);

 

Sometimes developers wonder how to pronounce the => token.

If the lambda expression is a predicate, expressing some condition: c => c.State == "WA" then the => can be spoken as "such that".  In this example, you could say "c such that c dot state equals Washington".  If the lambda expression is a projection, returning a new type: c => new XElement("CustomerID", c.CustomerID); then the => can be spoken as "becomes".  In the above example, you could say "c becomes new XElement with a name of CustomerID and its value is c dot CustomerID".  Or "maps to", or "evaluate to", as suggested in the comments below.  But most often, I just say "arrow".  J

A quick note: predicates are simply boolean expressions that are passed to some method that will use the boolean expression to filter something.  A lambda expression used for projection takes one type, and returns a different type.  More on both of these concepts later.

The Func Delegate Types

The framework defines a number of parameterized delegate types:

public delegate TR Func<TR>();

public delegate TR Func<T0, TR>(T0 a0);

public delegate TR Func<T0, T1, TR>(T0 a0, T1 a1);

public delegate TR Func<T0, T1, T2, TR>(T0 a0, T1 a1, T2 a2);

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

 

In the above delegate types, notice that if there is only one type parameter, it is the return type of the delegate. If there are two type parameters, the first type parameter is the type of the one and only argument, and the second type is the return type of the delegate, and so on. Many of the standard query operators (which are just methods that you call) take as an argument a delegate of one of these types.

Expression Trees

Lambda expressions can also be used as expression trees.  This is an interesting topic, but is not part of this discussion on writing pure functional transformations.

[Table of Contents]  [Next Topic]

 

Posted: Tuesday, October 03, 2006 10:43 PM by EricWhite

Comments

The private life of Alex Thissen said:

Time to continue with the longest running series on C# 3.0. Lambda expressions originated from lambda

# December 6, 2006 3:01 PM

Alex Thissen Weblog Build 1.15.10.1971 said:

Time to continue with the longest running series on C# 3.0. Lambda expressions originated from lambda

# December 6, 2006 3:52 PM

Alex Thissen Weblog Build 1.15.10.1971 said:

Time to continue with the longest running series on C# 3.0. Lambda expressions originated from lambda

# December 8, 2006 1:56 PM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# March 2, 2007 12:46 AM

Ken Brubaker said:

One of the questions I've had about the new lambda expression syntax in C# 3.0 is how to pronounce it...

# June 7, 2007 4:59 PM

Luca Biader said:

Really brief and nice. I like it ! And this article, of course ... :)

# August 10, 2007 11:31 AM

Yan Virin said:

I think that the => operator should be pronounced as "induces", as it does in fommal logics.

# August 28, 2007 7:01 AM

Francis said:

Great article - feels like it's pitched right at me.

You could pronounce "=>" as "returning" - it works in both your examples.

# October 18, 2007 8:50 AM

Mirrored Blogs said:

Body: I arrived a bit late in the morning and missed the opening Keynote on Silverlight by Jason Zander

# October 20, 2007 12:09 PM

Happy Coding :) said:

Do you want to know what's new in the 3rd version of the lovely C# :) ? just check the links below:

...

# November 30, 2007 7:35 PM

anonymous said:

it's a little difficult between telling the difference between this and a normal function call.  i think people would be better served if you passed the delegate into a quicksort function for pedagogical purposes.

# January 13, 2008 6:50 PM

Lica Aurelian George said:

Hello there

 I found this article by searching on google. What can I say, I made some tests regarding Lambda Expressions. One of them is that, for sure, the parameters are still STRONGLY TYPE. Just analyze that :

public delegate T SomeDelegate<T> (T A,T B);

and then :

SomeDelegate<String> calcul = (x, y) =>

{

  MessageBox.Show(x.GetType().ToString());

  return String.Empty;

};

So, the typeof(x) is String, just like the type value that was passed for the "SomeDelegate<T>".

There are much more things interesting regarding Lambda Expressions. I used them most of all in custom Extention Methods.

# January 19, 2008 12:18 PM

Lica Aurelian George said:

Or... try that :

MessageBox.Show(

           ((SomeDelegate<String>)((x, y) =>

           {

                   MessageBox.Show(x.GetType().ToString());

               return (x + y);

           })).Invoke("2", "3").ToString()

           );

# January 19, 2008 12:27 PM

dave^2=-1 said:

Reading Anders' post on Lexical Closures, Deferred Execution and Kicker Methods with respect to LINQ

# February 1, 2008 5:49 AM

Dan said:

I'm a little late to the dance; however, great explaination on the white-box use of lamda expressions.  Thank you... -Dan

# March 29, 2008 1:04 PM

Jagadish Krishnan said:

An article, concise and to the point. "Keep it simple" is the way to go.

# March 31, 2008 8:35 AM

EE said:

Other names I use for "=>" are "maps to" or "evaluates to". But ofcourse no answer is "right" ;-)

# April 10, 2008 10:52 AM

George said:

In JavaScript lambdas are just regular functions.  For example, this expression throws a lambda

throw function(x) x * x;

which can be caught later and called as a regular function.  Not that it is of any use but demonstrates the flexibility.

# May 8, 2008 7:51 PM

Eric White's Blog said:

I had an interesting conversation with my nephew the other day. He is a very bright CS student working

# July 24, 2008 2:06 AM

WCF群组博客 said:

PostedbyscottonTuesday,May08,2007 ThisarticlelooksatJavaScrip...

# August 1, 2008 12:02 AM

chadmyers said:

Another name for 'statement lambdas' is 'blocks'.

Are you planning a follow-up to talk about some more advanced uses, like closures?  Closures, in my experience, tend to surprise people and they don't usually get it at first, so that might be something else cool to cover.

As far as naming the => operator, in Ruby circles, it's known by the name of a certain member of the male anatomy starting with the letter 'P' :)

# August 30, 2008 9:28 AM

chaiguy1337 said:

I generally pronounce "=>" as "goes to", but I also like "maps to" and "evaluates to".

@chadmyers: Remind me never to involve myself in any Ruby circles. :P

# October 2, 2008 1:45 PM

EricWhite said:

@chadmyers, the post on closures is now written:

http://blogs.msdn.com/ericwhite/archive/2008/09/12/closures.aspx

-Eric

# October 9, 2008 5:15 PM

Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 said:

If you are using Linq to SQL, instead of writing regular Linq Queries, you should be using Compiled Queries

# October 27, 2008 3:26 PM

Omar AL Zabir blog on ASP.NET Ajax and .NET 3.5 said:

If you are using Linq to SQL, instead of writing regular Linq Queries, you should be using Compiled Queries

# October 27, 2008 3:33 PM

Mac Nawaz said:

=> is actually pronounced as "goes to"

# November 8, 2008 1:19 AM

Garfield said:

Hey Eric,

Thanks for the great article.  I've been searching the net for a good explanation of Lambda Expressions and by far yours is the best.  I really like how you walks us through the process from C# 1.0 to C#3.0 showing the progression.  By doing that you made the transition very easy to follow.  It's wonderful when someone is explaining something and they don't make the assumption that you have previous knowledge.  By walking us through the progression I don't think anyone can leave this article not understanding the topic.  Well done, I'll have to check out your other articles.

Regards,

Garfield.

# December 31, 2008 8:28 AM

EricWhite said:

Thanks, Garfield - I appreciate the compliment.  :)

# January 5, 2009 7:47 PM

Scott Dorman's Blog said:

Note : This entry was originally posted on 11/28/2008 11:58:09 AM. I present at a lot of the local Florida

# January 10, 2009 6:30 PM

朽木 said:

WhatASP.NETDevelopersShouldKnowAboutJavaScript转自:http://odetocode.com/Articles/473.aspxPosted...

# April 3, 2009 12:43 AM

c0ut said:

"All lambda expressions use the lambda operator =>, which is read as "goes to" "

http://msdn.microsoft.com/en-us/library/bb397687.aspx

# April 5, 2009 2:15 PM

Aninda said:

awesome Eric. I hope you keep making concepts easier to understand. Thank you.

# June 24, 2009 1:07 PM

Warren LaFrance said:

Excellent work!  You really made this much easier to grasp and more importantly use in my code...

Thanks

# August 26, 2009 6:51 PM

JohnR said:

I've recently switched over from Java to C#, subsequently bought two books from Manning but was struggling to understand delegates and lambda expressions. I understood it immediately when I read your article. It's excellent, thanks.

# August 28, 2009 8:08 AM

Alan said:

Very good article and thanks!

I just wonder what is: () => Could you please explain this one also? I encountered this a lot in "Composite Application Guidance for WPF and Silverlight" which I keep confused.

Example:

           var myAction = new ActionHelper()

                              {

                                  ActionToExecute =

                                      () => calledThreadID = Thread.CurrentThread.ManagedThreadId

                              };

and:

               ServiceLocator.SetLocatorProvider(

                   () => new MockServiceLocator(

                       () => mockRegionContentRegistry));

Thanks

Alan

# August 30, 2009 3:46 PM

EricWhite said:

Hi Alan,

What you're seeing is a statement lambda expression that takes no arguments, and returns void.  Here is similar code that you can paste into a console application and run:

Action a = () =>

{

    Console.WriteLine("in a statement lambda expression that takes no arguments and returns void.");

};

 

a();

There are various flavors of the Action delegate type, just like there are various flabors of the Func delegate type.  Actions are delegate types that return void.

What you're seeing in the "Composite Application Guidance for WPF and Silverlight" is that there is a void delegate that takes no arguments, and they are using Lambda expression syntax as a convenient way to initialize the delegate.  They could have written a function, declared and initialized a delegate, and assigned the delegate, but this would be more verbose.

Does that help?

-Eric

# August 30, 2009 7:17 PM

Alan said:

Eic:

Thank you very much for your timely response. The code makes sense to me now. I've been Googling the () => and couldn't find any thing until your posting showed up.

Thanks

Alan

# August 30, 2009 11:34 PM

Dinkar Jaitly said:

Nice article with clear breakup of lambda expresssion.

# October 21, 2009 7:42 AM

Nutan said:

Thank you, it helped to grab the basics of Lambda Expressions.

# October 22, 2009 2:18 AM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker