Submitted by BillB on 12/9/2009

(If you have a minute, please add a comment when you're done so I know if I'm presenting this well enough.)

C# Delegates and Lambdas

Edited 8/1/2010

Contents

Delegates are Used as Callback Arguments Back to Top

Before getting into the details of delegates and lambdas, a quick overview.

You can think of a delegate as an object that represents a method. You can use the delegate object to call the method that it represents instead of calling the method directly but there's little benefit to doing this just because you can. Delegates become useful when you pass them to other methods as arguments, so the called methods can call the method that the delegate references. When you pass the delegate around like this it's a callback argument and it's commonly done in all software, not just .Net. I don't talk alot about callbacks here but I do include an example of one that I made up as well as one used in .Net. When you're done learning about delegates and lambdas here, check out a related article, callbacks with delegates and interfaces to learn more about how they're used.

Here's where anonymous methods and lambdas come in. A lambda is just a cleaner looking C# syntax for callback arguments. Instead of passing a delegate object as a callback argument, you could pass the whole method itself in the form of an anonymous method. But you'd only do this if the method is short, like one or two lines; coding a longer method as an argument in a method call wouldn't be pretty. But even if your method is just one line, you probably wouldn't do this because C# offers what is called a lambda, which is simply another syntax to write an anonymous method and makes for slick looking code. There are a lot of .Net API's that take a callback argument and often the code that runs as a callback is very simple and short so it's easily written in lambda syntax. (Later, I'll show how easy lambdas are to understand.) So, I think of delegate objects and anoymous methods and lambdas all as delegates, though technically, you could disagree. It is correct to say that you can pass either a delegate or an anoymous method or a lambda as an argument to a method that takes a delegate as a parameter; they can all be used as callback arguments.

One of the important things the C# compiler does to support delegates as callback arguments is called delegate inference. It's key to understanding how delegates are used in C# and I'll get to it in due time, so read on. First we need to go to square one and understand exactly what a delegate is. I didn't understand C# delegates until I understood what the compiler was doing behind the scenes. Without this understanding I was just memorizing syntax. After reading articles online as well as several C# books, I still didn't really get it. (There are so many BAD tech books out there.) That is, until I found Jon Skeet and Jeffrey Richter. (Thanks guys, for two excellent C# books.) I experimented with some code and finally wrote this article to make sure I understood the concepts and so others might benefit.

Delegates in C# 1.0 Back to Top

A delegate is an object like any other, which, in C# 1.0, you had to declare and instantiate. But new .Net 3.5 delegate types and a smarter C# 2.0 compiler made the code around delegates different; cleaner and what is often described as more expressive. We'll avoid these newer developments for now because while they allow for more expressive source code, they hide what a delegate really is. Here's what you had to do in C# 1.0:

  1. Define a delegate type - A delegate type will define the signature of the method that it will refer to and is type-safe as a result. So before you create your delegate type, you need to know what method it will refer to.
  2. Create an instance of the delegate type and assign it a value.
  3. Use the delegate object for some purpose: "Invoke the delegate".
using System;
namespace DelegatesTutorial
{
    class Program
    {
        // 1. Define a delegate type
        public delegate bool IsEvenDelegate(int number);

        static void Main(string[] args)
        {
            // 2. Create an instance of the IsEvenDelegate type
            IsEvenDelegate isEvenDelegate = new IsEvenDelegate(IsEven);

            // 3. Invoke the delegate instance
            Console.WriteLine("Is 8 even? " + isEvenDelegate.Invoke(8));

            Console.ReadKey();                
        }

        // A named method that I'll refer to with a delegate
        private static bool IsEven(int number)
        {
            return (number % 2 == 0);
        }
    }
}

Even this C# 1.0 code should confuse you because the compiler is doing work for you behind the scenes, hiding the true nature of a delegate.

What is the C# 1.0 Compiler Doing?

Let's see what's going on here. When I defined the IsEvenDelegate type,

public delegate bool IsEvenDelegate(int number);
the compiler generated something like this:
internal class IsEvenDelegate : System.MulticastDelegate
{
   public IsEvenDelegate(Object obj, IntPtr method);
   public virtual void Invoke(Int32 number);
   public virtual IAsyncResult BeginInvoke(Int32 val, AsyncCallback callback, Object obj);
   public virtual  void EndInvoke(IAsyncResult result);
}

Now that looks more like something I'm used to. Now I can see that a delegate is a class like any other class. The delegate class inherits from MulticastDelegate, which MSDN tells us has a couple of Properties, Method and Target, which expose the fields, _target and _methodPtr. The Method property gets the method that the delegate represents and the Target gets the class instance of the method. So these fields together are looking like they could comprise a pointer to a method. We don't need to understand the nitty gritty of how this pointer-thing works in C# to understand delegates but we can now see that a delegate isn't exactly a pointer, C# is too high-level for that but it sure contains something that looks a lot like one you'd see in a lower level language.

But this is confusing: The constructor generated by the compiler takes two arguments but our constructor call in the source code passes in only one, the name of the method, so something's going on behind the scenes to create the _target and _methodPtr fields.

And finally, we see the Invoke method that we used. The BeginInvoke and AsyncCallback support asyncronous tasks, which we can ignore for this discussion.

So, a delegate is a type that wraps or encapsulates a method. We still don't know all the details of how everything's working, like exactly how the constructor is working or how the pointer works but that detailed knowledge isn't necessary to understand our delegate code.

C# 2.0 Back to Top

C# 2.0 and .Net Framework 2.0 do even more to allow for cleaner and more concise code. The new functionality mystifies delegates even more for people who've not been coding C# from the beginning, which is why delegate tutorials usually start with the old ways of C# 1.0.

using System;
namespace DelegatesTutorial
{
    class Program
    {        
        // 1. Delegate type definition is no longer needed-it's built-in

        static void Main(string[] args)
        {
            // 2. Use built-in Predicate<T> type.  Don't need new keyword anymore.
            Predicate<int> isEvenDelegate = IsEven;

            // 3. Invoke the delegate instance - but where's the "Invoke"
            Console.WriteLine("Is 8 even? " + isEvenDelegate(8));

            Console.ReadKey();
        }

        // A named method that I'll refer to with a delegate
        private static bool IsEven(int number)
        {
            return (number % 2 == 0);
        }
    }
}

What's new?:

  1. We no longer need to define a delegate type because, the .Net Framework 2.0 included a bunch of delegate types that define just about any method signature you'd ever need. The Predicate<T> type is a generic delegate that you can use to wrap any method that returns a bool and takes a single argument, a type of your choice. In our example we use an int; Predicate<int>. Besides Predicate<T>, the .Net library also includes the following delegate types, each aptly named for the kind of work they do.
    • A series of generic Func<> types for methods that take up to 16 arguments and return a value.
    • A series of Action Types for methods that take up to 10 arguments and return void.
    And there's more in the System namespace.
  2. The compiler now does something called delegate inference which means you can assign the name of a method directly to a delegate variable; and you don't need the new keyword anymore. Delegate inference allows for clean and expressive code when passing a lambda statement to a method that has a delegate parameter, which you'll see in the real world example at the end of this article.
  3. A compiler shortcut allows you to leave off the .Invoke. Now isEven, the delegate, is called just like IsEven(), the method.

Anonymous Methods Back to Top

In many cases, when the code that a delegate refers to is short, named methods are overkill and can be replaced by an anoymous method. Let's see how to eliminate our IsEven named method and assign our isEvenDelegate to an anoymous method.

We assigned the delegate directly to the code from the method. We've replaced the method name, IsEven, with the delegate keyword. Otherwise, the method looks the same as the named version. The return type, bool in this case, is implied by the method itself and the compiler is smart enough to figure out that "return(number % 2 == 0)" means the return type is a bool.

Predicate<int> isEvenDelegate = delegate(int number)
{
    return (number % 2 == 0);
};

// Or without carriage returns
Predicate<int> isEvenDelegate2 = delegate(int number){ return (number % 2 == 0); };

This code is fairly ugly but Lambda syntax comes to the rescue.

Lambdas Back to Top

A lambda isn't that scary; it's just another syntax for coding an anonymous method; a more terse syntax that's expressive and easy to code in many situations when passing a callback argument into a class library. The Linq extension methods on IEnumerable<T> are a prime example. As with most new language features, you'll have trouble understanding them unless you know what the compiler is doing behind the scenes.

Here's the basic syntax:

=> is the lambda operator. To the right of the lambda is the method body; the statements. To the left of the operator are the input arguments.

// An anonymous method 
delegate(int number){ return (number % 2 == 0); };

// This busy lambda works but it's so ugly
(int number) => { return (number % 2 == 0); }

// In lambda syntax - terse version -- a smart compiler at work
number => number % 2 == 0
I show two versions of the lambda syntax. The first is very busy looking and the second has no clutter and is more readable. The busy version is instructive as an intermediate step between the anonymous method syntax and the terse lambda syntax but I don't think you'd want to code it that way. Comparing the anonymous method and the terse lambda, what have we eliminated?
  • The delegate keyword is gone.
  • The paramter type is gone. The compiler figured out that the number param is an int.
  • The return is gone.
  • The parentheses and curly braces are gone.

We've eliminated all the noise. Anonymous methods are going the way of the dinosaurs, replaced by lambdas. They take a little getting used to but some practice will have you fluent in no time. You have to admit, they make for good looking code. However, when your lambdas start getting bigger, some punctuation is required. Once your lambda exceeds a few statements or a few input params, you might use a named method instead. It turns out that in the real world, in the .Net class library, there are many methods, (API's), that take a delegate that can usually be written with one statement. We'll see examples in a bit.

I mentioned earlier that .Net comes with lots of delegate types built in; Funcs and Actions and Predicates. Here are a few examples of statements that instantiate objects of a few of those built-in delegates using lambdas:

// A Func that takes two ints and returns an int 
Func<intintint> MultiplyTwoIntsDelegate = (num1, num2) => num1 * num2;

// A Func that takes two ints and returns a bool 
Func<intintbool> CompareNum1PlusTenAndNum2 = 
    (num1, num2) => { num1 += 10; return num1 > num2; }; 
    
// An Action that takes no params and returns void 
Action ActionDelegate = () => 
    Console.WriteLine("Action delegates take no parameters - use empty parens");

Note that there's another whole world of lambda expressions that has nothing to do with expressing a method or delegates. In another context, a lambda expression may be translated into a data structure called an expression tree and then processed by some other code that translates the tree into something completely different, like SQL statements to hit a backend relational databse. That's called LINQ to SQL. LINQ to XML translates the lamda expression into XML queries. You can even do Amazon.com searches with LINQ to Amazon, (yes it really exists). So don't get confused by apples when they're really oranges.

MulticastDelegate Back to Top

We saw earlier that Delegate inherits from System.MulticastDelegate, which has the fields that serve as the actual pointer to a method. It has another field, _invocationList, that supports chaining of delegate instances. You can chain delegate instances, sort of like a list of pointers to methods, so when you invoke the head delegate, the whole chain runs. The Delegate class has Combine() and Remove() methods to add or remove delegates from the list. I won't get into it here but mention it to be thorough. Events often use this feature to open itself to multiple subscribers. Jeffrey Richter's excellent book, CLR via C# has good information on the topic. You've got to read his book; he's got a 3rd edition out in 2010.

Play Time Back to Top

Here's a console app for experimenting. It includes :

  • Examples of anonymous methods passed as arguments
  • Lambdas
  • Two different named methods to show a delegate argument as a callback
Copy it and have at it.
using System;
namespace DelegatesTutorial
{
    class Program
    {
        static void Main(string[] args)
        {
            // Use built-in Predicate<T> type and assign an anonymous method to it.
            Predicate<int> isEvenDelegate = delegate(int number)
            {
                return (number % 2 == 0);
            };

            // Or without carriage returns
            Predicate<int> isEvenDelegate2 = delegate(int number){ return (number % 2 == 0); };

            Console.WriteLine("Is 8 even? " + isEvenDelegate2(8) + " - An anonymous method");

            // Expressing an anonymous method with lambda syntax
            Predicate<int> isEvenDelegate3 = number => number % 2 == 0;
            Console.WriteLine("Is 8 even? " + isEvenDelegate3(8) + " - A lambda");


            // Now let's start using our named method, IsTheNumberEven
            // This is serve as an example of a callback.
            // Call the IsItEven method and send it the delegate for a callback
            IsTheNumberEven(isEvenDelegate, 5, "Predicate delegate assigned to an anoymous method");

            // Call IsItEven and for the callback, send it an inline anonymous method.
            // Carriage returns are used here as they usually are when writing a method.
            IsTheNumberEven(delegate(int number)
            {
                return (number % 2 == 0);
            }, 5, "An anoymous method");

            // Call IsItEven and for the callback, send it the anonymous method inline.
            // No Carriage returns.
            IsTheNumberEven(delegate(int number) { return (number % 2 == 0); }, 5, "An anoymous method");

            // Send a lambda statement
            IsTheNumberEven(number => number % 2 == 0, 5, "Lambda");

            // A busy lambda works too
            IsTheNumberEven((int number) => { return (number % 2 == 0); }, 5, "Lambda");

            // Call SumIt and have it sum the products of the numbers 1 thru 4, each multiplied by ten.
            int sumOfNumX10s = SumIt(1, 5, x => x * 10);
            Console.WriteLine("Result of my method call to SumIt with a Lambda param: {0}",
                sumOfNumX10s);

            // Now lets change how sumIt does it's job.  Add up the squares.
            int sumOfSquares = SumIt(1, 5, x => x * x);
            Console.WriteLine("Result of my method call to SumIt with a Lambda param: {0}",
                sumOfSquares);

            Console.ReadKey();
        }
        

        // Method to write out true if a number is even, false if it's odd.
        // The code that determines whether the number is odd or even is located elsewhere.
        // A reference to that code code, a callback, is passed in as a paramter.
        public static void IsTheNumberEven(Predicate<int> isEven, int number, string message)
        {
            Console.WriteLine("Is {0} even? {1} - {2}", number, isEven(number), message );
        }

        // Another example  - SumIt's functionality is dictated by it's caller.
        public static int SumIt(int start, int stop, Func<intint> process)
        {
            int z = 0;
            for (int i = start; i < stop; i++)
            {
                z = z + process(i);
            }
            return z;
        }
    }
}

Real World .Net Example : List<T>.FindIndex(Predicate<T> match) Back to Top

The FindIndex method on List<T> receives a Predicate as an argument. The Predicate is a callback that the FindIndex method calls to determine what it's looking for. (I wrote an article on callbacks. that you might read if you're interested.) Here's the definition from MSDN along with the definition of Predicate :

// List<T>.FindIndex from MSDN
public int FindIndex(Predicate<T> match)

// Predicate<T> from MSDN - it's a delegate
public delegate bool Predicate<T> (T obj)
In the example below, the T in Predicate<T> is a string and the Predicate delegate is wrapping a method that takes a string and returns a bool. The example will be looking for a car that's a Subaru. Here's how the Predicate looks in various forms:
// Named Method 
bool IsItASubaru(string car)
 {
     // String.Contains returns a bool
     return car.Contains("Subaru");
 }

// Anonymous Method
delegate(string car) { return car.Contains("Subaru"); }

//Lambda
car => car.Contains("Subaru")
And here's an example:
using System;
using System.Collections.Generic;

namespace DelegateInDotNetExample
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> cars =
               new List<string> { "Ford 300""Toyota Solara""Subaru Outback""SAAB 93" };
            // Delegate inference at work here
            int index = cars.FindIndex(car => car.Contains("Subaru"));

            Console.WriteLine("The first Subaru in the list is at index {0}, and it's a {1}",
                index, cars[index]);
           
            Console.ReadKey();
        }
    }
}

The compiler is helping make this code expressive, (less clutter in the form of curlies, parens, no new keyword required for delegate instantiation, etc.).

Delegate inference is letting us assign an anonymous method, (which we wrote using lambda syntax), directly to a delegate, in this case a Predicate. The compiler, using delegate inference, is making sure that cars => car.Constains("Subaru") has the right signature for a Predicate, and then it creates code to instantiate a delegate type and assign our method to it.

For me, understanding delegate inference eliminated my lambda fears. Before, I'd look at a signature of a method that took some kind of delegate, like the Predicate in this example and I just didn't GET how an anoymous method argument passed muster. That stuff makes me crazy unless I know what's going on.

So because the compiler is doing this stuff for you, delegates, anonymous methods and lambdas start to look like the same thing; at least on the surface. I'm starting to use the words lambda and delegate interchangeably. Anonymous methods get left out in the cold because they're rarely used now that lambda syntax is available. So, there's lots going on behind the scenes but now that we know how it all works, we can can enjoy the expressivness and readability our code can have.

Linq Back to Top

The mother lode of methods that take delegate parameters are the Linq extension methods on IEnumerable<T>. I'd have used one for an example here but there's more to explain that is off topic. Now that you know delegates through and through, you're ready to tackle linq to objects. Check out my article on Linq to objects.

Variable Scope Back to Top

One last thing I'll throw in briefly about anonymous methods because it's interesting. A lambda or anonymous method has access to any variable in the method where the lambda is defined; it's called a captured variable once it has been referenced in the lambda. A captured variable will be immune from garbage collection once it has been captured by a delegate for possible use later. For more information on captured variables and closures in C# you've got to go to Jon Skeets blog on closures.

Click a star

Comments

By Scotty McCreery on 5/25/2011 11:39:00 PM
Things clear up after I read your artcile.I read a program before with a lot of Delegates, linking here and there and yet getting me nowhere. Both articles (C# Delegates and Lambdas) and (C# Callbacks with Interfaces and Delegates) of yours is a must read in order to understand what Delegates and callback is all about. You have nailed it, You did it very well. Thank you

By Lee Dewyse on 5/25/2011 11:45:00 PM
Without reading and understand your both articles on Delegates, it is impossible for me to undertand other people's program, even though I read through the program 20 times. After reading your articles for two times (this artcile, then C# Callbacks with Interfaces and Delegates and then back to this artcile again), Wow, suddenly all the delegate in others program look so smart and clearer. It is beautiful. Your article is beautiful, and I say : I love it. Thank you

By ameer on 10/11/2011 9:50:00 PM
Nice work man

Add your comment: