Page 2 of 3
An arithmetic of delegates
You may well know the += operator for adding to the invocation list but there is also a -= operator that can be used to remove methods.
In this case -=b will remove the last occurrence (in execution order) of the delegate that is equal to b.
Equality between delegates is defined so that equal delegates have to be of the same type and encapsulate the same method – Target and Method. Notice that this is a change from version 1 of C# where equal delegates could be different types.
Also notice that two MulticastDelegates are considered equal if their invocation lists are identical and in the same order.
Delegates don’t provide direct access to their invocation list and you can’t manipulate it directly. However you can retrieve the invocation list as an array of Delegates.
Delegate InvList =
returns a delegate array with two elements – a delegate wrapping Hello and a delegate wrapping Goodbye. You can even invoke each delegate in the invocation list by enumerating the array:
foreach (Delegate D in InvList)
You might be puzzled as to why we use DynamicInvoke rather than Invoke?
The reason is that neither Delegate nor MulticastDelegate support an Invoke method. When you use the classes directly in this way the invocation of the method cannot be checked at compile time, hence the need for a “DynamicInvoke”.
Some of the simplicity of using a MuticastDelegate comes from the overloading of the += and -= operators but there are other, perhaps surprising ways, that you can work with invocation lists.
For example, you can create a delegate that has the combined invocation list of other delegates using the “+” operator:
greetType DelA = hello;
greetType DelB = goodbye;
DelC = DelA + DelB;
In this case DelC encapsulates the methods of DelA and DelB. Similarly the “-“ operator removes one delegate’s invocation list from another.
DelC = DelC - DelA;
removes all of the delegates in the invocation list of DelA from DelC.
It is also worth knowing that there are static methods defined on the Delegate class such as Combine and Remove which can be used to manipulate arrays of Delegates as well as pairs of Delegates.
A common misconception is that .NET events are just multicast delegates. This is mostly true but an event has some additional added infrastructure.
An event is a multicast delegate with the addition of two accessor functions, add and remove, that take over the adding and removal of delegates from the invocation list. Most of the time you can ignore the existence of the accessor functions as the system will provide default implementations for you and, as the += and -= operators are overloaded and call these default accessor functions, you can use an event as if it was a simple delegate.
The basic idea is that a class can provide an event that any clients can subscribe to simply by adding delegates to the invocation list of the event’s multicast delegate. The event can only be “raised” by the class that owns the event and this results in each delegate in the invocation list being called.
Events are mostly generated automatically for us by Visual Studio but to really understand what is going on you can’t do better than implement a custom event manually.
First we need a suitable delegate type:
public delegate int MyNewEventType(
This we convert into an event:
public event MyNewEventType MyNewEvent;
MyNewEvent is now an event instance which wraps an anonymous instance of the delegate type. We can add a delegate to the event in the usual way:
You can also use anonymous methods and lambda expressions to add delegates to an event:
MyNewEvent += (string param) =>
MessageBox.Show("Goodbye " + param);
To raise the event, we simply call it as if it was a delegate: