我建立了一个事件系统,该事件系统维护一个dictionary
的代表,并通过通用的Subscribe / Unsubscribe方法(每个动作执行dictionary
)向此type
添加/删除元素T),并具有Publish方法,以在发生某些情况时通知订阅者(该方法也采用T类型的Action)。一切正常,但是我注意到在向dictionary
添加或删除元素时不能使用+ =或-=,因为传递给方法的类型(T的动作)与存储在其中的类型不匹配。 dictionary
(Delegate
)。以下代码段显示了我可以做什么和不能做什么。
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;
}
}
我在这里+= operator for Delegate特别是Jon Skeet的答案,这部分
当两个操作数都具有某种委托类型D时,binary +运算符执行委托组合。(如果操作数具有不同的委托类型,则会发生绑定时错误。)
我不明白的是这个
编译器将其转换为对Delegate.Combine
的调用。反向操作使用-或-=,使用Delegate.Remove
。
当我使用+ =或-=而不是Delegate.Combine
时到底发生了什么?两者之间有什么区别,一个实现有效,另一个实现无效?
答案 0 :(得分:5)
在您链接的答案末尾,它说:
由于
System.Delegate
不是委托类型,因此未为其定义运算符+
。
这说明了为什么它不起作用(两个操作数均为Delegate
):
delegates[typeof(T)] += del as Delegate;
Delegate.Combine
之所以有效,是因为it is declared like this:
public static Delegate Combine (params Delegate[] delegates);
请注意它如何接受类型为Delegate
的参数,而不是特定的委托类型。如果代表的类型不同,它将抛出ArgumentException
。
因此,编译器不仅将+
运算符更改为Delegate.Combine
,而且还进行了一些类型检查!另一方面,如果直接使用Delegate.Combine
,则不会进行编译时类型检查。 Delegate.Combine
仅在运行时检查类型。
所有其他行都有效,因为您正在进行强制转换,即告诉编译器委托的类型,使+
的两个操作数都为Action<T>
类型。