Delegates and Events are really powerful parts of C#. They are also powerful confusing. We can start off by making a new delegate type:
delegate void SimpleEvent () ;
This is a new type, called SimpleEvent. If we ever need to create a delegate that refers to a method that returns void and has no parameters, we can use SimpleEvent to do this. So, let’s do that. Here is our method:
This method doesn’t do much, but it does tell us it has been called, which is a start. Now, to create something that refers to this method we can create a SimpleEvent instance:
SimpleEvent x = new SimpleEvent(testMethod);
This has created a delegate that refers to testMethod. We’ve given it the rather enigmatic name of x. We can make a call on this delegate if we want:
Note that we have to treat x as if it was a void method that accepts no parameters (since that is the type of method that the delegate refers to). When x runs it will print out “Test Called”, since that is what testMethod does, and x presently refers to that method.
The name x is actually quite appropriate, in that when we call x we don’t really know what is going to happen, since it could be made to refer to any method. If it doesn’t refer anywhere we’ll get a null reference exception of course, and serve us right.
So, delegates let us create objects that can refer to methods we want to run. Great if you want to bind behaviours to events. (and this is where it starts to get confusing)
We can declare a delegate variable:
At the moment this refers nowhere (try to call eventList and we get an exception). But we can add methods that we want to be called when the event is fired:
eventList += new SimpleEvent(testMethod);
Now, when we do:
- the testMethod is called. Wonderful. So let’s make this more confusing:
eventList += x;
This adds another item on to the list of delegates managed by eventList. The item added is the x that we created earlier, which refers to testMethod. Now, when we do:
- the testMethod gets called twice (because when you call a delegate it works through all the methods that are presently bound to it).
If we want to unhook methods from a delegate then we can use –= to do this:
eventList –= x;
This would remove one of the calls of testMethod from the delegate, so that now if we call eventList it will only call testMethod once. And it works.
However, this works too:
eventList –= new SimpleEvent(testMethod);
I hate this. It confuses me so much. It looks like we’ve made a new delegate and minused (!) it from the list of events. There is some strong magic going on here which I really don’t like. What must happen is that the –= operator must go “Aha!, here is a delegate that references this method, I must remove one from the list of delegates”.
If x is the delegate that I originally created, it seems reasonable to remove that from the list, what confuses me is that you can also remove delegates by appearing to create new ones. I guess that this is because otherwise programmers would have to keep track of event references that they might like to remove later, but I still don’t like it.