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/2010Contents
- Delegates are Used as Callback Arguments
- Delegates in C# 1.0
- C# 2.0
- Anonymous Methods
- Lambdas
- MulticastDelegate
- Play Time
- Real World .Net Example : List<T>.FindIndex
- Linq
Delegates are Used as Callback Arguments 
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 
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:
- 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.
- Create an instance of the delegate type and assign it a value.
- Use the delegate object for some purpose: "Invoke the delegate".
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 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 
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.
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?:
-
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.
- 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.
- A compiler shortcut allows you to leave off the .Invoke. Now isEven, the delegate, is called just like IsEven(), the method.
Anonymous Methods 
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.
{
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 
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.
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
- 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:
Func<int, int, int> MultiplyTwoIntsDelegate = (num1, num2) => num1 * num2;
// A Func that takes two ints and returns a bool
Func<int, int, bool> 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 
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 
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
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<int, int> 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) 
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
public int FindIndex(Predicate<T> match)
// Predicate<T> from MSDN - it's a delegate
public delegate bool Predicate<T> (T obj)
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")
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 
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 
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.
Comments
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
Nice work man