Delegates & Events - A short Q&A
The other day I gave a presentation about Delegates & events to folks who were new to C#. I dawned on me that in fact, this subject is kind of confusing, and several questions arose from this presentation.
Disclaimer: this is intended to be read by people already familiar with the Delegates and Events syntax, and is mostly related to C# syntax, since VB.Net syntax is a little different (simpler) in some cases.
Q: What’s the difference between a Delegate and a MultiCastDelegate?
A: There is no real difference. Every delegate is a MultiCastDelegate, but in order to be logically called a MultiCastDelegate, it has to have more than one target in its Invocation list (multiple targets==multiple cast).
So, in essence, once you have created a delegate, you've created a MultiCastDelegate with an invocation list count of 1.
Q: What’s the difference between a delegate and an event?
A: I’ll divide the answer into 2 parts.
Syntax wise:
Here’s how one could define a delegate in a class:
public class Class1
{
public delegate void DomSomethingDelegate(int num1,int num2);
public DomSomethingDelegate MyDeleageteCallback;
}
And here’s how I would declare an event of this delegate:
public class Class2
{
public delegate void DomSomethingDelegate(int num1,int num2);
public event DomSomethingDelegate MyDeleageteCallback;
}
Notice that syntactically, the only difference is that I place an “event” keyword before the delegate variable declaration. That’s it.
So what’s the “event” keyword adding to this?
Well, to understand this, consider Class1 in the code above. If I was using this class, as a client I could set it’s delegate variable like this:
Class1 c = new Class1();
c.MyDeleageteCallback+=new
Class1.DomSomethingDelegate(this.Calculate);
This simple code adds a new target to the delegate’s invocation list, which is perfectly fine. In fact, this same code will word with Class2. 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:
Class1 c = new Class1();
c.MyDeleageteCallback=new
Class1.DomSomethingDelegate(this.Calculate);
This piece of code will work just fine with class1, but if we were to try to use it on class2, where there is the event keyword declared, we would 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 I 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 imagine that 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.