Introduction to LINQ: Part II - Lambda Expressions

This is part two of my introduction to LINQ tutorial. If you have not read part one and do not have a decent understanding of delegates in C# then please head over and read that first.

Table of Contents

Resources


Part II - Lambda Expressions

Now that you have a decent understanding of delegates and anonymous methods, it will be much easier to introduce you to the concept of lambda expressions. As always, if possible, I like to start off with a quote from the MSDN.

A lambda expression is an anonymous function that can contain expressions and statements, and can be used to create delegates or expression tree types.

All lambda expressions use the lambda operator =>, which is read as "goes to". The left side of the lambda operator specifies the input parameters (if any) and the right side holds the expression or statement block. The lambda expression x => x * x is read "x goes to x times x." This expression can be assigned to a delegate type as follows:

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

The easiest way to think about a lambda expression is as a short-hand method. For example, take this method:

public int AddNumbers(int x, int y)  
{
    return x + y;
}

This simple method could easily be translated into a lambda expression: (x,y) => x + y;. That's it! That entire method was simplified into a quick expression. The cool thing about lambdas is that they can now be used in place of anonymous methods and assigned to delegates. So if we were to update our first console application it should look like this:

class Program  
{
    delegate int PerformCalculation(int x, int y);

    static void Main(string[] args)
    {
        PerformCalculation blackBox = (x, y) => x + y;

        Console.WriteLine("Result: {0}", blackBox(9000, 1));
        Console.ReadLine();
    }
}

Now isn't that much cleaner than anything we were doing before? Named methods were far too verbose for this simple function and even anonymous methods looked a little silly when created the old fashioned way. Lambda expressions simplify the task of encapsulating simple logic so much that I couldn't imagine programming without them anymore.

Lambdas are defined by the lambda operator => which, as stated on the MSDN, reads as "goes to". The left side of the operator is where the input parameters are defined (the method arguments). The right side of the operator is the function to be performed. There are several ways to form a lambda expression.

1) Parenthesis are optional around the input parameters if only one parameter is present:

x => x.ToString();  

2) No parameters or more than one and the parenthesis are required:

(x, y) => x + y;
() => Console.WriteLine("I am an anonymous method that accepts no arguments.");

3) Lambdas can also have statement blocks if need be:

x =>  
{
    string value = x.ToUpper();
    Console.WriteLine(value);
}

Number 3 starts to look a little more like a normal method but it's nice to know that the option is there to use a statement block if you need to.

While the idea of lambda expressions is simple, their power is immense. As a quick example of lambdas in a more practical usage, let's update our second console app from part one (the one that filtered our list of sci-fi shows) to use lambda expressions. It should look something like this:

class Program  
{
    delegate bool EvaluateCondition(string value);

    static void Main(string[] args)
    {
        // Create a list of sci-fi shows.

        List<string> scifiShows = new List<string>
        {
            "Star Trek: The Next Generation",
            "Star Trek: Voyager",
            "Star Trek: Deep Space Nine",
            "Battlestar Gallactica",
            "Doctor Who",
            "Stargate SG-1",
            "Stargate Atlantis",
            "Stargate Universe",
            "Futurama"
        };

        // Get a filtered list of shows by calling FilterList() and passing in our list of shows and a
        // lambda expression to be used when checking the values in the list.

        List<string> filteredList = FilterList(scifiShows, x => x.StartsWith("Star Trek"));

        // Print each show in the filtered list to the console.

        foreach (string show in filteredList)
        {
            Console.WriteLine(show);
        }
        Console.ReadLine();
    }

    /// <summary>
    /// Filters a string list based on a delegate function used to check each value in the list.
    /// </summary>
    /// <param name="list">The list to be filtered.</param>
    /// <param name="evaluateCondition">The delegate to be invoked when checking each value.</param>
    /// <returns>The filtered string list.</returns>
    static List<string> FilterList(List<string> list, EvaluateCondition evaluateCondition)
    {
        List<string> filteredList = new List<string>();

        foreach (string show in list)
            if (evaluateCondition(show))
                filteredList.Add(show);

        return filteredList;
    }
}

The usefulness of lambda expressions should be starting to show to you now. See how simple it was to pass in an anonymous method to be used when filtering our list of sci-fi shows? A simple lambda does all the work. No named methods and no full-blown anonymous methods either, just a simple short-hand expression.

Func

You'll notice above that even though the lambda expression greatly simplified the code we pass into the FilterList() method, we still had to declare the delegate at the top of the class. If we needed multiple delegates that accept different input parameters and return different output parameters, we would have to define a new delegate for each type of method. That is painful and annoying. In comes Func<in T, out TResult>.

Declaring a Func is a short-hand way of declaring a delegate with an output type and a specified number of input parameters and the type of each. For example, take this delegate:

delegate int PerformCalculation(int x, int y);  
static void Main(string[] args)  
{
    PerformCalculation calculator = (x, y) => x + y;
    Console.WriteLine(calculator(1,2));
}

The Func equivalent of this delegate would look like this:

static void Main(string[] args)  
{
    Func<int, int, int> calculator = (x, y) => x + y;
    Console.WriteLine(calculator(1,2));
}

Notice that I no longer need to declare the delegate. I was able to create the delegate on the fly using the short-hand Func type. The first two types listed between the angle brackets are the first two input parameter types (which both happen to be int). The third one is the type of the output (which also happens to be int). Func<> allows you to declare up to 16 input parameters; any more than that and you'll need to declare your delegate the old fashioned way, though personally I've never seen a delegate that takes in more than five or six input parameters.

Let's put our new Func type to use in that same sci-fi show list filtering program. It should look like this:

class Program  
{
    static void Main(string[] args)
    {
        // Create a list of sci-fi shows.

        List<string> scifiShows = new List<string>
        {
            "Star Trek: The Next Generation",
            "Star Trek: Voyager",
            "Star Trek: Deep Space Nine",
            "Battlestar Gallactica",
            "Doctor Who",
            "Stargate SG-1",
            "Stargate Atlantis",
            "Stargate Universe",
            "Futurama"
        };

        // Get a filtered list of shows by calling FilterList() and passing in our list of shows and a
        // lambda expression to be used when checking the values in the list.

        List<string> filteredList = FilterList(scifiShows, x => x.StartsWith("Star Trek"));

        // Print each show in the filtered list to the console.

        foreach (string show in filteredList)
        {
            Console.WriteLine(show);
        }
        Console.ReadLine();
    }

    /// <summary>
    /// Filters a string list based on a delegate function used to check each value in the list.
    /// </summary>
    /// <param name="list">The list to be filtered.</param>
    /// <param name="evaluateCondition">The delegate to be invoked when checking each value.</param>
    /// <returns>The filtered string list.</returns>
    static List<string> FilterList(List<string> list, Func<string, bool> evaluateCondition)
    {
        List<string> filteredList = new List<string>();

        foreach (string show in list)
            if (evaluateCondition(show))
                filteredList.Add(show);

        return filteredList;
    }
}

Pretty snazzy eh? No more delegate declaration at the top of the class. We now have a simple method that accepts a Func<string, bool> delegate and we pass it a simple lambda expression. It doesn't get much better than that does it? I think you can imagine now the power behind this. The ability to encapsulate bits of code and pass them around our applications so easily is one of the main building blocks necessary for LINQ to exist. But before we can move onto LINQ itself there is another concept you will have to learn called extension methods.

Part III - Extension Methods

Chev

Read more posts by this author.

comments powered by Disqus