I've built an event system that maintains a dictionary
of delegates, adds/removes elements to this dictionary
via generic Subscribe/Unsubscribe methods (which each take an Action of type
T), and has a Publish method to notify the subscribers when something happens (which also takes an Action of type T). Everything works fine, but I've noticed I cannot use += or -= when adding or removing elements to my dictionary
, as the types passed into the methods (Action of T), do not match the types stored in the dictionary
(Delegate
). The following snippet shows what I can and cannot do.
private readonly Dictionary<Type, Delegate> delegates = new Dictionary<Type, Delegate>();
public void Subscribe<T>(Action<T> del)
{
if (delegates.ContainsKey(typeof(T)))
{
// This doesn't work!
delegates[typeof(T)] += del as Delegate;
// This doesn't work!
delegates[typeof(T)] += del;
// This is ok
delegates[typeof(T)] = (Action<T>)delegates[typeof(T)] + del;
// This is ok
var newDel = (Action<T>)delegates[typeof(T)] + del;
delegates[typeof(T)] = newDel;
// This is ok
del += (Action<T>)delegates[typeof(T)];
delegates[typeof(T)] = del;
// This is ok
delegates[typeof(T)] = Delegate.Combine(delegates[typeof(T)], del);
}
else
{
delegates[typeof(T)] = del;
}
}
I mostly understand Jon Skeet's answer here += operator for Delegate specifically, this part
The binary + operator performs delegate combination when both operands are of some delegate type D. (If the operands have different delegate types, a binding-time error occurs.)
What I don't understand, is this
The compiler turns it into a call to Delegate.Combine
. The reverse operation, using - or -=, uses Delegate.Remove
.
What exactly is going on when I use += or -=, versus Delegate.Combine
? What are the differences between the two, making one implementation valid, and another invalid?
Delegate is a function pointer. It holds the reference of one or more methods at runtime. Delegate is independent and not dependent on events. An event is dependent on a delegate and cannot be created without delegates.
A delegate is a method with a parameter and a return type. A delegate is a type that safely encapsulates a method. Delegates are object-oriented, type safe, and secure.
Delegates are pointer to functions and used for call back. Multicast delegates help to invoke multiple callbacks. Events encapsulate delegate and implement publisher and subscriber model.
A delegate is a type that represents references to methods with a particular parameter list and return type. When you instantiate a delegate, you can associate its instance with any method with a compatible signature and return type. You can invoke (or call) the method through the delegate instance.
At the end of the answer you linked, it says:
Since
System.Delegate
is not a delegate type, operator+
is not defined for it.
This explains why this does not work (both operands are Delegate
):
delegates[typeof(T)] += del as Delegate;
Delegate.Combine
works because it is declared like this:
public static Delegate Combine (params Delegate[] delegates);
Note how it accepts parameters of type Delegate
, instead of a specific delegate type. And it will throw an ArgumentException
if the delegates are not of the same type.
So the compiler not only changes the +
operator to Delegate.Combine
, it also does some type checking! On the other hand, no compile-time type checking is done if you use Delegate.Combine
directly. Delegate.Combine
only checks the types at runtime.
All the other lines work because you are casting i.e. telling the compiler what type the delegates are, making both operands of +
to be of type Action<T>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With