For once and for all: Delegates, Events, Anonymous Methods and Lambda Expressions

What started as a simple concept, Delegates and Events, has turned into a major subject in the .NET framework with newcommers like Anonymous Methods and Lambda Expressions. In this post I hope to shed some light on what all these are and how they interact. Mind you however that all that is written in this post is not new and has been described in more detail by many other much more smarter people then me. So, allthough I will touch on the various aspects of the subject, for detailed discussions and how certain features work I will forward you to those posts. It is not my goal to repeat what allready has been said, but I wanted investigate what is possible and share my results with you. This way I thought to provide in one post a detailed summary on what is possible and how it’s done.

It is my hope that after reading this post and reading the referenced articles, one would have an in depth knowledge of delegates, events and the lot.

Delegates

The basic construct for all the above is the delegate. For those familiar with C++: a delegate can be seen as similar to a function pointer in that it allows you to pas a reference to a method around and then later call that method. There are however some differences between them resulting in people trying to emulate delegates in C++

For those unfamiliar with C++, this Stack Overflow article has a nice explanation:

The best analogy that I’ve found to explain delegates it’s a testament or your last will.

It’s a set of instructions that of course you write before you die, and you leave it in a safe place. Then after your death, your attorney will execute those instructions…

Delegates are used mostly when the code that wants to execute the actions doesn’t knows the enough details of what that action should be, you can view it as a sequence of actions to be executed at the appropriate time.

Declaring a delegate

Declaration of a delegate is done in C# using the delegate keyword:

// A delegate is a type of itself, so you
// can declare it outside the scope of a class
delegate int SomeMethodDelegate(string arg);

This declaration declares a delegate which can call methods that return an integer and have a string as their single argument. A delegate is a type of it’s own, so a delegate can be declared outside the scope of a class unlike methods and properties. But just as a type (class, struct, …) can not be declared inside a method, neither can a delegate. If you declare a delegate using the above syntax, you are actually declaring a type derived from the Delegate type. Actually, it’s derived from the System.MulticastDelegate type.

Using the delegate

Instantiating the delegate and binding a method to it is as simple as:

// Provided you have an object delegateDemo of a class which implements 
// a method called MethodCall which takes a string and returns an integer
SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);

Using the delegate is similar to invoking the method

int i = delegateReference("String argument");

There is a more longwinded way of instantiating delegates and invoking them directly involving the Delegate class. I will not illustrate it here but you can find more information about it in the Stackoverflow question “Possible to instantiate and invoke a delegate by name?”

Delegates are “Multicast”

In the .Net framework, delegates are multicast. What this means is that you can bind more then one method to a delegate:

SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);
delegateReference += new SomeMethodDelegate(delegateDemo.SomeOtherMethodToCall);

If you now invoke the delegate, the two methods bound to the delegate will be called. If a method in the chain throws an exception, latter methods will no longer be called. You can avoid this by iterating the multicast delegate invocation list yourself.

Life made easy

Delegates are practical beasts and you can use them in lot’s of places. To help you and to prevent you’d have to declare new delegate types all over the place, Microsoft declared some delegate types in the .Net Framework which you can use out of the box:

Action Delegate 
Action<T> Generic Delegate 
...
Action<T1, T2, T3, T4> Generic Delegate

These encapsulate methods with no return value and zero to 4 arguments.

So, whenever you find the need to write code like

delegate void YourDelegate(int, double, string);
YourDelegate yourDelegateInstance;

you can instead write:

Action<int, double, string> yourDelegateInstance;
Func<TResult> Generic Delegate 
Func<T, TResult> Generic Delegate 
...
Func<T1, T2, T3, T4, TResult> Generic Delegate 

These encapsulate methods with a return type and zero to 4 arguments.

You can find more about predefined delegates here.

Deep dive

There is also another, more powerfull, way of instantiating delegates. If you take a look at the MSDN documentation of the Delegate type, then you will see it has a method CreateDelegate which has a number of overriden signatures of which Delegate.CreateDelegate Method (Type, Object, MethodInfo, Boolean) is the most generic one. Where in the above samples the assignment of the delegate also specifies the object to call the method from, with this method it is possible to postpone this decision untill you actually call the instantiated delegate, by providing the object as an argument to the delegate.

delegate void OpenMethodDelegate(DelegateDemo target);

class DelegateDemo
{
  public DelegateDemo(string arg)
  {
    m_arg = arg;
  }

  public void MethodToCall()
  {
    Console.Write("This method got called on object DelegateDemo[" + m_arg + "] using a delegate.\n");
  }
}
	
MethodInfo method = typeof(DelegateDemo).GetMethod("MethodToCall", BindingFlags.Public | BindingFlags.Instance);
OpenMethodDelegate nonBoundDelegate = (OpenMethodDelegate)Delegate.CreateDelegate(typeof(OpenMethodDelegate), null, method);
DelegateDemo delegateDemo1 = new DelegateDemo("delegateDemo1");
nonBoundDelegate(delegateDemo1);
DelegateDemo delegateDemo2 = new DelegateDemo("delegateDemo2");
nonBoundDelegate(delegateDemo2);

With the above delegate declaration, you can create 4 different delegate instantiations, all documented here. In the sample code with this post you can see an implementation of the 4 possibilities.

Events

Events are technically essentialy the same as delegates, only they have been declared with the modifier “event”. Thus, they are a special kind of delegate: a “modified” delegate. However they serve a different semantic purpose.

Declaring an event

Because an event is a special kind of instance of a or is a modified delegate, you declare events as a special type of instance of the delegate.

delegate int SomeMethodHandler(string arg);
public event SomeMethodHandler SomeMethodEvent;

You could compare it with declaring a const:

int i;		   // The normal type (in the above this is the delegate)
const int j;	// The modified type (in the above this is the event)

The type of modification it does is however completely different. (and then again, it’s not, but you will read about this further).

Using the delegate as an event

Instantiating the event and binding it to a method is done like:

eventDemo.SomethingHappenedEvent += new EventDelegate(eventDemo_SomethingHappenedEvent);

Notice how we used the “+=” operator instead of the simple assignment operator as done with regular delegates. This is one of the effects of using the event modifier on the delegate. What actually happens when you use the event modifier on a delegate is the following:

  1. A field is created on your class with the type of the delegate.
  2. “Add” and “Remove” accessor methods are created to access that field. These two methods are generaly called “Event Accessors”

This is much in the same way as when you declare a property to access a field. This is also why the above descibes the implementation of what is called “Field like events”. The above syntax is a C# shortcut for accessing those add and remove handlers.

Using the event-delegate is similar to invoking a method.

SomethingHappenedEvent();

What is not visible in this code is the fact that this call can only be made inside a method of the class declaring the event. The event field can not even be accessed in a class deriving from the class declaring the event. This also is an effect of using the event modifier on the delegate instance.

If you want to provide access to derived classes, Microsoft suggests declaring so called “On” handler methods:

event MyCorrectEventHandler MyCorrectEvent;
event EventHandler<MyCorrectEventArgs> TheSameButWithoutTheDelegate;

protected virtual void OnMyCorrectEvent(MyCorrectEventArgs e)
{
  EventHandler<MyCorrectEventArgs> handler = TheSameButWithoutTheDelegate;
  if (handler != null)
  {
    e.SomeValue = 1;
    handler(this, e);
  } 
}

In the derived class, you then raise the event by calling this On… method.

The “event” modifier: what does it do?

The event keyword in C# is actually a modifier on the delegate type. What it modifies is the visibility of certain members of the delegate so that effectively you can only access the Combine and Remove methods of the Delegate type, that being the reason why you can only add or remove delegate handlers.

Some conventions

The above code, allthough correct, is not the common way of using events. Microsoft provides some guidelines on how to declare and use event in the .NET Framework:

  • The delegate for the event has no return value.
  • The delegate for the event always has two parameters, the first of type object and referencing the object that fires the event, and the second an EventArgs derived class which identifies details of the event.

In the above you will probably recognize the typical eventhandler signature from windows forms:

void button_ClickHandler(object sender, System.EventArgs e)

Life made easy

When make heavy use of events in your code, you will find yourself declaring lots of events. That would require you to also write lots of delegates for those events, all with this same basic structure of a method taking an object and a EventArgs derived class.

To make life easier Microsoft provides two delegate for you to prevent this clutter:

EventHandler Delegate 
EventHandler<TEventArgs> Generic Delegate 

So instead of having to write

delegate void MyPersonalEventHandler(object sender, EventArgs e);
event MyPersonalEventHandler MyPersonalEvent;

You can now write

event EventHandler MyPersonalEvent;

Or if you have your own event arguments:

class YourEventArgs : EventArgs {... }
event EventHandler<YourEventArgs> YourEventWithSpecialArguments;

Deep dive
The above illustrates the most common way of using the event modifier on delegates. If you look at the documentation for the event modifier you will notice that there is also the possibility of declaring events as virtual, abstract, etc… Whereas the event modifier changes the visibility of certain members of the delegate, declaring an event as virtual or abstract actually changes the the implementation of the event much in the same way as declaring a property as virtual or abstract.

Just as a abstract or virtual properties provide just the signature for the property getter and setter methods, an abstract or virtual event provides just the signature for the event “add-er” and “remove-er” methods.

You can then provide your own implementations for the event accessor methods. Being able to provide your own accessor methods implementations is however not a privilege for abstract and virtual events, but can be done for every event.

Again, in the sample code you can see an implementation of this.

Anonymous methods

Since C# 2.0 there is a new syntax for attaching methods to delegates named Anonymous methods. Well, this is actally an over-simplification of anonymous methods. But let’s stick with this simplification for a minute.

Declaring an anonymous method

In the Delegate section you learned that attaching a method to a delegate is done by creating the method in a class first and then assigning that method to the delegate:

delegate int SomeMethodDelegate(string arg);

class ClassWithMethod
{
   int MethodToCall(string arg) { ... }
}

SomeMethodDelegate delegateReference = new SomeMethodDelegate(delegateDemo.MethodToCall);

This can be cumbersome because it obligates you to create a method in a class which you will not always want to do. So C# 2.0 provides you the possibility to declare that method inline with the assignment to the delegate:

SomeMethodDelegate d = delegate(string param) { Console.WriteLine("Param: " + param.ToString()); };
d("A Parameter");

This can be very handy in certain situations like sorting of items in a list.

Deep dive

Now why is this an oversimplification? Because with the syntax of Anonymous Methods comes a programming construct more generaly known as Closures to C#.

What closures allow you to do is use the variables known in the scope declaring the anonymous method, inside the anonymous method. As an example:

public static void UsingLocal()
{
  int i;
  i = 1; 
  Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Local[" + i.ToString() + "]"); };
  d(2);
}

This even extends to the fields of the class in which the declaring scope resides:

class AnonymousMethodDeepDive
{
  private int m_field;

  public AnonymousMethodDeepDive(int field)
  {
    m_field = field;
  }

  public int Property { get; set; }

  public void UsingField()
  {
    Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Field[" + m_field.ToString() + "]"); };
    d(1);
  }

  public void UsingProperty()
  {
    Action d = delegate(int param) { Console.WriteLine("With Parameters[" + param.ToString() + "] and Property[" + Property.ToString() + "]"); };
    d(1);
  }
}

What essentialy happens is:

  1. The compiler generates a class, capturing all the local variables as proeprties of that class.
  2. The compiler generated class has as a method the anonymous method, thus making it’s properties (and thus tha variables in the decalring scope) available to the anonymous method.

There are a few optimizations in some special cases, but the above is the most generic way to look at these.

Now, if you think you understand all this, then read these two posts.

Lambda Expressions

Lambda Expressons are in their most basic form a more convenient syntax for anonymous methods. Again, their is a lot more to lambda expressions then this, but those features have nothing to do with delegates so I will not discuss them in this post.

Syntax

The most generic way for writing lambda expressions is:

Func f1 = (int x, string y) =&gt; { Console.WriteLine("A Return Value And Two Parameters: " + x.ToString()); return x + 1; };

In this assignment statement the form

() => { }

is the lambda expression.

Now, there are a few simplifications possible:

Because C# supports parameter type inference, you can drop the type specifiers for the arguments:

Func f1 = (x, y) => { Console.WriteLine("A Return Value And Two Parameters: " + x.ToString()); return x + 1; };

If you have a single statement, you can drop the curly braces and the semicolon:

Action d4 = (x, y, z) => Console.WriteLine("Three Parameters: [{0}][{1}][{2}]", x, y, z);

If you have a single parameter, you can drop the parameter braces:

Action d2 = x => { Console.WriteLine("One Parameter: " + x.ToString()); };

If you have a single statement, which is the return value, you can drop the “return” keyword:

Func f2 = x => x + 1;

Code

You can download the code here

One thought on “For once and for all: Delegates, Events, Anonymous Methods and Lambda Expressions

  1. What an article….. Really amazed to see the explanation and use of delegates, Anonymous Methods etc.
    Thanks

Leave a comment