+ =和Delegate.Combine之间的区别

Chr*_*ley 5 c# delegates

我建立了一个事件系统,该事件系统维护一个dictionary委托,dictionary通过通用的Subscribe / Unsubscribe方法(每个方法都采用Action typeT)向其中添加/删除元素,并具有一个Publish方法,以在发生某些情况时通知订阅者。采取类型为T的动作)。一切正常,但是我注意到在向元素添加或删除元素时不能使用+ =或-= 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我在这里特别了解Jon Skeet的答案+ =代表运算符,这部分

当两个操作数都具有某种委托类型D时,binary +运算符将执行委托组合。(如果操作数具有不同的委托类型,则发生绑定时错误。)

我不明白的是

编译器将其转换为对的调用Delegate.Combine。反向操作使用-或-=使用Delegate.Remove

当我使用+ =或-=时,到底发生了什么Delegate.Combine?两者之间有什么区别,使一种实现有效而另一种无效?

Swe*_*per 5

在您链接的答案末尾,它说:

由于System.Delegate不是委托类型,+因此未为其定义运算符。

这就解释了为什么它不起作用(两个操作数都是Delegate):

delegates[typeof(T)] += del as Delegate;
Run Code Online (Sandbox Code Playgroud)

Delegate.Combine之所以有效,是因为这样声明

public static Delegate Combine (params Delegate[] delegates);
Run Code Online (Sandbox Code Playgroud)

请注意,它如何接受type的参数Delegate,而不是特定的委托类型。ArgumentException如果委托的类型不同,则会抛出一个。

因此,编译器不仅将+运算符更改为Delegate.Combine,还进行了一些类型检查!另一方面,如果Delegate.Combine直接使用,则不会进行编译时类型检查。Delegate.Combine仅在运行时检查类型。

其他所有行均有效,因为您正在进行强制转换,即告诉编译器委托的类型是什么,使两个操作数都+为type Action<T>