Home > .NET 3.5, C# 3.0 > Upgrade your C# Skills part 3 – Lambda Expressions

Upgrade your C# Skills part 3 – Lambda Expressions

December 5, 2007

I’ve been very busy continuing my C# 3.0 and .NET 3.5 self-education. I’ve been focusing primarily on LINQ, but before I cover that here, which will take several postings, I wanted to cover Lambda Expressions. If you have been reading about LINQ and its related technologies at all, you’ve surely come across this term already. If you’ve already read some about Lambdas, then perhaps you came to the same conclusion I did: a lot of writers covering Lambda Expressions seem to want you to be boggled by them. In most articles, I found myself wading through a bunch of stuff I really did not need to know. In fact, it sometimes simply added more confusion.

So my goal in this article is to bypass all the pocket protector stuff and get right down to brass tacks. Here are a list of things I will NOT be covering that pervade almost every other article about Lambda Expressions:

  • Lambda calculus
  • Anonymous Methods
  • Functional Languages
  • Lexical Closures

If you are interested in any of the above, they are plenty of other articles out there. If, however, you are like me and just want to use this stuff, then read on…

Anonymous Methods

Before you scream foul, yes, I said I wasn’t going to discuss these, and really, I’m not. Or more accurately, I’m not going to explain them or show examples. You do have to know that Lambda Expressions are just another way to write Anonymous Methods. *whew*! Glad we got that out of the way!

The tricky part, though, for many programmers is knowing when to use Anonymous Methods. As far as our discussions go, it will be pretty easy: you want to use Anonymous Methods whenever you need to pass a method reference. This is done by use of delegates, something else I’m not really going to talk about.

So what you need to know is this: where ever you see a method that requires a delegate (or a reference to a method), you can use a Lambda Expression instead. An Anonymous Method is just a way to write the code for such a delegated method inline. So, we just need a way to know when we can use Lambda Expressions.

Actions, Predicates, and Funcs

What we need are Delegate Types. Delegate types are declared signatures for method calls that are used to wrap instance methods or, in our case, anonymous methods. Fortunately for us, there are some Generic Delegate Types built in to .NET that we can put to good use.

Action<T>

This is a Generic Delegate defined in .NET that will wrap and execute a method, passing it a variable of type T. Here is the MSDN Documentation. If you use this in a method declaration, you can actually pass a reference to a method, anonymous or otherwise, to a method of your own creation. For an example, check out this Extension Method:

public static void ExecuteOnValues<K, V>(this IDictionary<K, V> sequence, Action<V> action)
{
    if (sequence == null)
    {
        throw new ArgumentNullException("sequence");
    }

    foreach (var item in sequence.Values)
    {
        action(item);
    }
}

You can see here that our method signature expects a Generic Action<T> method reference. What we don’t know is what this method will do. The code line action(item) is saying “execute the method passed in on my action parameter, and pass it the item as a parameter.” So our Action method receives the Value of our Dictionary as a parameter and does something with it. We are going to use Lambda Expressions to define the “something”. Here is a simple example:

var dict = new Dictionary<int, string>();
dict.Add(1, "Coding");
dict.Add(2, "in");
dict.Add(3, "C#");
dict.Add(4, "Rules!");

dict.ExecuteOnValues(f => Console.WriteLine(f.ToString()));

Here we have created a new Dictionary<TKey, TValue> collection and added some data. Because Dictionary<TKey, TValue> inherits from IDictionary<TKey, TValue>, we can use our new Extension Method to execute some code against all the values in our Dictionary. But remember that our Extension Method really has no executing logic: it is expecting us to send it a reference or a delegate to it so it knows what to do. Enter the Lambda Expression. In the ExecuteOnValues method call above, f => Console.WriteLine(f.ToString()) is a Lambda Expression.

Anatomy of a Lambda Expression

// A simple Lambda expression
f => Console.WriteLine(f.ToString())

The “=>” thingy in the middle is the Lambda operator. This is what lets you know a Lambda is what is happening here. Let’s break the rest down into two parts: the left side and the right side. The left side represents a parameter list to be passed into the method. The right side represents the code the method will execute. Really, that’s it. You can make it harder if you want, but ultimately this is all it boils down to. Here is a diagram:

// A simple Lambda expression
f     =>    Console.WriteLine(f.ToString())
PARM Lambda CODE TO EXEUTE

So you can think of this as a method defined like so:

// A faux method representing a Lambda
void Method (unknownType f)
{
    Console.WriteLine(f.ToString());
}

In essence, without getting into all the pocket-protector details, this is what is the compiler is doing for you when it sees a Lambda Expression. The above is psuedo-code, and not entirely accurate, but you get the idea.

Where this gets confusing is that you really don’t see any type declarations, either for the parms or the return value. This is more Compiler Inference at work. In our example above, we specified that our Action generic was based on the Value Type of the Dictionary. The Compiler is able to look at the context of the Lambda Expression and simply infer that f is whatever type we specified on the Action parameter. You could write the details out, specifying the types, but not needing to is one of the major draws of Lambdas: the code is more compact and it “just works”. Now we’ll change our Dictionary to have a different Value type. We’ll make it our standard Person and add some people to it:

var dict2 = new Dictionary<int, Person>()
{
    {1, new Person() {FirstName = "John", LastName = "Smith", Age = 32, DOB = "12/31/1988"}},
    {2, new Person() {FirstName = "Jimmy", LastName = "Crackcorn", Age = 57, DOB = "08/08/1934"}},
    {3, new Person() {FirstName = "Mary", LastName = "Contrary", Age = 44, DOB = "09/10/2000"}}
};
dict2.ExecuteOnValues(f => Console.WriteLine("{0} is a {1} born on {2}", f, f.GetType().Name, f.DOB));

Now if we run this we’ll get these results (Click for full size image):

Person List
And now we get to see something else: in this Lambda, I am executing methods and Properties on my parameters. Pretty cool, huh?

So let’s read this Lambda out loud: “GIVEN f, EXECUTE {Console..WriteLine(“{0} is a {1} born on {2}”, f, f.GetType().Name, f.DOB));}”

Confused about the Looping? Don’t be: the loop is actually happening back in our Extension Method. All that’s happening here is that this code is executing (inside the loop) and using each Value from our Dictionary as the GIVEN parameter.

Predicate<T>

This is a Generic Delegate that evaluates a condition and returns true or false. Notice that Action<T> did not return any values. Predicate<T> is different because it returns a boolean value, and ultimately its only purpose is to determine whether or not a certain condition is met. Here is the MSDN documentation.

Let’s create a custom PersonCollection class and add a method that returns a sublist of Person objects who meet an unspecified criteria:

class PersonCollection : List<Person>
{
    public List<Person> MatchingPersons(Predicate<Person> condition)
    {
        List<Person> list = new List<Person>();

        foreach (Person p in this)
        {
            if (condition(p))
            {
                list.Add(p);
            }
        }

        return list;
    }
}

This code is specific to our PersonCollection class but still takes advantage of Predicate<T> to filter itself into a subsetted list. Let’s execute this now and get back just a list of Veterans:

var people = new PersonCollection()
    {new Person() {FirstName = "John", LastName = "Smith", Age = 32, DOB = "12/31/1988", IsMilitaryVeteran=true},
     new Person() {FirstName = "Jimmy", LastName = "Crackcorn", Age = 57, DOB = "08/08/1934", IsMilitaryVeteran=false},
     new Person() {FirstName = "Mary", LastName = "Contrary", Age = 44, DOB = "09/10/2000", IsMilitaryVeteran=true}};

Console.WriteLine("Print them all:");
people.ForEach<person>(f => Console.WriteLine("{0} is a {1} born on {2}", f, f.GetType().Name, f.DOB));
Console.WriteLine();

// Get a subset of people
var veterans = people.MatchingPersons(f => f.IsMilitaryVeteran);
Console.WriteLine("Print just veterans:");
veterans.ForEach<person>(f => Console.WriteLine("{0} is a {1} born on {2}", f, f.GetType().Name, f.DOB));

The beauty here is we did not specify what the criteria for the filtering was: we could have just as easily asked it for all the people whose first names begin with the letter “J”:

// Get another subset of FirstName beginning with "J"
var js = people.MatchingPersons(f => f.FirstName.StartsWith("J"));
Console.WriteLine("Print just Js:");
js.ForEach<person>(f => Console.WriteLine("{0} is a {1} born on {2}", f, f.GetType().Name, f.DOB));

Here is a screen shot of running all three of these in a row (Click for full size image):

Screenshot

Personally, I think this is a great tool, and the Lambda Expressions just make it that much more readable and easy to develop.

Func<T>

So far, we’ve seen Generic Delegates that return void and bool. That’s nice, and we can do a lot with them, but sometimes you need something more. This is where FUNC<T> comes in to play: it can return any type. In this case, the T is the return type. In the MSDN Documentation, they use “TResult” instead of “T”, so I’ll do that too. There are five Func Generic Delegates defined in .NET 3.5:

  • Func<TResult> – no parameters, returns type TResult
  • Func<T, TResult> – 1 parameter, returns type TResult
  • Func<T1, T2, TResult> – 2 parameters, returns type TResult
  • Func<T1, T2, T3, TResult> – 3 parameters, returns type TResult (are you noticing a pattern yet?)
  • Func<T1, T2, T3, T4, TResult> – 4 parameters, returns type TResult

What’s cool about Func is that you can create your own methods on the fly and give them meaningful names. Here is a simple example:

// Get a subset of people using Func
Func<Person, bool> isVeteranBeginsWithJ = f => f.IsMilitaryVeteran && f.FirstName.StartsWith("J");
Console.WriteLine("Print just veterans whose first name's begin with \"J\":");
foreach (Person p in people)
{
    if (isVeteranBeginsWithJ(p))
    {
        Console.WriteLine("{0} is a {1} born on {2}", p, p.GetType().Name, p.DOB);
    }
}

As you can see, I simply use my Func as any other method. I can see where this would come in very handy for short term reusability. Also, a lot of LINQ elements require Func delegates, so you have to have it in your toolkit.

Some odds and ends

There are a few items that I have to mention. First of all, Action<T> also has a few multiple parameter options:

  • Action<T1, T2>
  • Action<T1, T2, T3>
  • Action<T1, T2, T3, T4>

We did not discuss sending multiple parameters to a Lambda. To do so, wrap them in parentheses, like so:

// Example from Microsoft
(x, y) => x == y

While Compiler Inference is at work here, it is not required. If you wish to specify types for readability you can:

// Example from Microsoft
(int x, int y) => x == y

Calling a Lambda with no parameters, such as Func<TResult> is done with empty parentheses:

Func<string> getSomething = () => "Something";
Console.WriteLine(getSomething());

Lambdas can access local variables:

string todo = "To Do";
Func<string> getSomethingTodo = () => "Something " + todo;
Console.WriteLine(getSomethingTodo());

And Lambdas can be just as complex as you want them to be. Here is a Lambda that receives our custom PersonCollection and calculates the average age based on the DOB (if you’ve looked at the initializers, you’ll find that the Ages and the DOBs do not balance):

Func<PersonCollection, int> calculateAverageAge =
    (PersonCollection c) =>
    {   int totalAges = 0;
        foreach(var p in c)
        {
            string[] parts = p.DOB.Split(new char[] { '/' });
            int year = int.Parse(parts[2]);
            int calcAge = DateTime.Now.Year - year;
            totalAges += calcAge;
        }
        int averageAge = totalAges / people.Count;
        return averageAge;
    };

Console.WriteLine("Average Age of collection is {0}", calculateAverageAge(people));

And lots more. This is hardly the definitive article on Lambdas, but hopefully it explains enough to get you started. There is certainly enough background here to begin using Lambdas with LINQ, which will be next in this series of articles. Here is a link to the MSDN Lambda Expressions (C# Programming Guide).

About these ads
Categories: .NET 3.5, C# 3.0
  1. February 6, 2008 at 9:42 am

    loved the series .. practical and precise.. great job !!!

  2. Renso
    September 4, 2008 at 7:50 am

    Great article!

  3. Abir
    September 22, 2008 at 2:59 am

    Down to earth useful guide, great work!

  4. Marc Roussel
    October 1, 2008 at 7:18 pm

    How do you exit a

    List().ForEach(delegate(Person p)
    {
    if(p.Name == “foo”)
    //HOW TO EXIT IMMEDIATLY ? Because break
    //isn’t accepted and return doesn’t exist at all
    });

    Thank you to email me instead of writing here since I may forget that I did come here…

  5. May 31, 2009 at 7:56 am

    Nice article but i am not sure if declaring variables inside a loop is a good idea and a good practice.

  6. Michael R.
    August 18, 2009 at 9:08 am

    A great article to get a basic understanding on delegate types and lambda expressions. Helped me a lot. Thanks.

  7. December 20, 2009 at 7:00 pm

    Thank you for this useful examples!

  8. Joe
    August 12, 2010 at 1:59 pm

    I was trying to test out the example and ran into a problem.

    dict2.ExecuteOnValues(f => Console.WriteLine(“{0} is a {1} born on {2}”, f, f.GetType().Name, f.DOB));

    Regarding Param {0} which maps to “f”(the object and not a member) if it is supposed to produce the first and last name as show in the console output then should not the extension call be like

    dict2.ExecuteOnValues(f => Console.WriteLine(“{0} is a {1} born on {2}”, f.FirstName + ‘ ‘ + f.LastName , f.GetType().Name, f.DOB));

  9. August 13, 2010 at 2:19 pm

    Hi Joe,

    Good eyes! The sample above is referencing a Person class, which has overridden .ToString(), so that is what gets printed. In the absence of that, your solution is correct.

  10. Rajeev Jha
    August 21, 2010 at 8:31 am

    Nice article. Very practical.

  11. Biff
    January 21, 2011 at 3:37 pm

    Great article!
    One thing though, I believe your average age calc should be
    `int averageAge = totalAges / c.Count;`
    instead of
    `int averageAge = totalAges / people.Count;`
    as you may pass in a different collection.

  12. Annie
    April 8, 2011 at 12:45 am

    Hi. Thanks for this great article. I’ve been looking for a easy-to-understand basic lambda expressions tutorial and this is certainly the best! Thanks again and more power.

  13. Awadhendra
    May 23, 2011 at 2:10 pm

    Its a beautiful tutorial. After reading this blog I understand about lambda expression. I had write a small blog on lambda expression which might be useful.

    http://www.mindstick.com/Blog/181/Lambda%20Expression%20in%20c

    Take a look its helpful for you.

  14. rasi
    July 9, 2011 at 7:42 am

    excellent! Thanks buddy

  15. July 16, 2011 at 11:37 am

    this is the programming language that I wish I’ve learned during my college.
    nice, thanks!

  16. December 9, 2011 at 10:25 am

    The blog is totally amazing and awesome. Please give more information from it.

  17. spade
    March 5, 2012 at 2:35 am

    It’s a work of art… thank you

  18. March 26, 2012 at 3:03 pm

    Hi
    Really you had written a very good article. Your way is very simple to explore your knowledge about lambda expression. I had also written a small blog on lambda expression that how to use lambda expression with use defined datatypes. I used lambda expression for finding records.

    http://dabbu-csharphelp.blogspot.in/2012/03/lambda-expression.html

    I hope this blog is also useful to those users who wants to know about lambda expressio that how to find records from list using lambda expression.

    thanks to sharing this useful article.

  19. April 30, 2012 at 8:39 am

    Thanks to usefull tips…..

    need to know about datagrid

  20. April 30, 2012 at 8:42 am

    hai friends ….deepak from ADDON technology…..
    any body to tel the mostly useage of oops in c#…. i wnt 2 know

    why asking means i am newly in c# program to code….. thts y asking

  1. December 11, 2007 at 10:32 am
  2. December 16, 2007 at 7:05 pm
  3. February 24, 2008 at 4:02 pm
  4. February 24, 2008 at 6:11 pm
  5. July 7, 2008 at 2:54 pm
  6. October 5, 2008 at 5:15 pm
  7. October 22, 2010 at 2:38 am
  8. May 13, 2013 at 10:15 pm
Comments are closed.
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: