delegates, anonymous methods and lambda

Lambda expression are very useful when writing LINQ queries, and they are often confused with delegates and anonymous method. In this post, I will try to clarify the differences and how they can be used in an application.

To start with, a delegate is a type that references methods. Delegates allow methods to be passed as arguments to other methods, or define callback methods and can be chained together (useful in Event Handling). Delegates can hold reference to multiple methods, and when that delegate is called, it runs all the methods that is attached to it. I’ll walk-through series of code to show how delegates are used, and where anonymous method and Lambda can be used.

To explain these concepts, I’ll be showing how delegates can be passed as arguments and used to filter a collection. Let’s say I have a Person class, and I want to iterate over a collection of Person objects and return a list of Person with Age greater than 17. What I’d do in this situation will be to create an extension method for an IEnumerable of Person (IEnumerable) and have it return a list that meets that condition, and call the method when needed.

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static IEnumerable<Person> GetAdults(this IEnumerable<Person> input)
{
    foreach (var person in input)
    {
        if (person.Age > 17)
        {
            yield return person;
        }
    }
}
## Program.cs ##
static void Main(string[] args)
{
    var people = new List<Person>()
        {
            new Person() {Age = 8, Name = "John"},
            new Person() {Age = 20, Name = "Scott"}
            ....
        };

    var adults = people.GetAdults();
    Print(adults);
}

At a later point, I may decide to filter a list of person objects to check for persons between the ages of 22 and 34. My next option will be to create another method with a different name, that does almost the same thing as our previous one, except that here the test condition changes. Another option will be to modify the GetAdults() method, allowing it to take a method which tests for different conditions and returns true if the condition is satisfied, as a parameter. In this case we can use a delegate as follows:

public delegate bool IsAdult(Person person);

public static IEnumerable<Person> GetAdults(this IEnumerable<Person> input, IsAdult test)
{
    foreach (var person in input)
    {
        if (test(person))
        {
            yield return person;
        }
    }
}

With this approach the calling code determines how and what to filter through the delegate type. To call this method we pass it any method from any accessible class or struct that matches the delegate type. This method can either be static or instance method. To do this I’ll create a static method that checks if the person’s age is greater than 17 and return true or false.

public static bool IsMatured(Person person)
{
    return person.Age > 17;
}

var adults = people.GetAdults(IsMatured);

With this approach I can create a method that checks if a person is between the ages of 20 and 34 and pass it to the GetAdults() and our code will execute as expected returning only objects that meets the condition. An alternative way to creating methods and passing them as a parameter is to use anonymous methods.

Anonymous methods is a way of writing inline code. It’s essentially a way to pass a code block as a delegate parameter. It saves us the pain of creating named methods. By using anonymous methods, you reduce the coding overhead of instantiating delegates because you do not have to create a separate method. There are times when named method is preferred over anonymous method, it’s only a matter of readability and functionality. The example above can be modified to use anonymous method as follows:

var adults = people.GetAdults(delegate(Person person) { return person.Age >= 18; });

//OR

var adults = people.GetAdults(delegate(Person person) { return person.Age > 21 && person.Age < 35; });

With this approach I can easily pass different methods that test for a condition to the GetAdults() extension method. A shorter way of writing anonymous methods is to use lambda expression. By using lambda expressions, you can write methods that can be passed as arguments or returned as the value of function calls. Lambda expression is divided into three parts. The first part represents the input parameter which is always on the left, the lambda operator (=>) and the expression or statement block on the right side which encapsulate the method execution body. You can assign this expression to a delegate type as follows:

var adults = GetAdults((person) => person.Age >= 18);

Now you see how easy it is to write anonymous methods using lambda. In summary, delegates holds reference to methods while anonymous method is a way of passing inline code to delegates as an alternative to named methods. Lambda expression on the other hand, is a short form of anonymous method.

Leave a comment