Friday, October 10, 2008

Delegate and Events

People often find it difficult to see the difference between events and delegates. C# doesn't help matters by allowing you to declare field-like events which are automatically backed by a delegate variable of the same name. In this posting, I will just touch the surface so that it will tickle you to go ahead read the references that are given at the end of the posting.

In his blog Roy Osherove has the following comments:

Here’s how you define a delegate in a class:

public class SampleDelegate
{
public delegate void DoSomethingDelegate(int num1, int num2);
public DoSomethingDelegate MyDelegateCallback;
}

And here’s how you declare an event of this delegate:

public class SampleEvent
{
public delegate void DomSomethingDelegate(int num1, int num2);
public event DomSomethingDelegate MyDelegateCallback;
}

Notice that syntactically, the only difference is that you place an “event” keyword before the delegate variable declaration.

So what’s the “event” keyword adding to this?
Well, to understand this, consider SampleDelegate in the code above. If you are using this class, as a client you could set it’s delegate variable like this:

SampleDelegate c = new SampleDelegate();
c.MyDelegateCallback += new SampleDelegate.DoSomethingDelegate(this.Calculate);

This simple code adds a new target to the delegate’s invocation list and the same code will work for SampleEvent.

SampleEvent c = new SampleEvent();
c.MyDelegateCallback += new SampleEvent.DomSomethingDelegate(this.Calculate);

There is no difference what so ever so far. But consider this code which, instead of adding a new target to the delegate’s Invocation list, simply sets the delegate to a new delegate:

SampleDelegate c = new SampleDelegate();
c.MyDelegateCallback = new SampleDelegate.DoSomethingDelegate(this.Calculate);

This piece of code will work just fine with SampleDelegate, but if you try to use it on SampleEvent, where there is the event keyword declared, youwould get a compilation error.

In essence, declaring the event keyword prevents any of the delegate’s users from setting it to null. Why is this important? Image that as a client you would add to the delegates invocation list a callback to one of my class’s functions. So would other clients. All is well and good. Now suppose someone, instead of using the “+=”, is simply setting the delegate to a new callback by using simply “=”. They basically just threw the old delegate and its invocation list down the drain and created a whole new delegate with a single item in its invocation list. All the other clients will not receive their callbacks when the time comes. It is this kind of situation that having the “event” keyword is aiming to solve.

In conclusion: an event declaration adds a layer of protection on the delegate instance. This protection prevents clients of the delegate from resetting the delegate and its invocation list, and only allows adding or removing targets from the invocation list.

For a deeper insight refer to the Jon Skeet's article - Delegates and events. Also Julien Couvreur's article C# events vs. delegates is worth reading.

No comments: