+ =和Delegate.Combine之间的区别

时间:2019-04-11 08:08:32

标签: c# delegates

我建立了一个事件系统,该事件系统维护一个dictionary的代表,并通过通用的Subscribe / Unsubscribe方法(每个动作执行dictionary)向此type添加/删除元素T),并具有Publish方法,以在发生某些情况时通知订阅者(该方法也采用T类型的Action)。一切正常,但是我注意到在向dictionary添加或删除元素时不能使用+ =或-=,因为传递给方法的类型(T的动作)与存储在其中的类型不匹配。 dictionaryDelegate)。以下代码段显示了我可以做什么和不能做什么。

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时到底发生了什么?两者之间有什么区别,一个实现有效,另一个实现无效?

1 个答案:

答案 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>类型。