+ = Delegate的运算符

jen*_*nsa 23 c# delegates

我知道+ =运算符会将一个方法添加到由Delegate基础对象维护的调用列表中

using System;

class Program
{

    delegate void MyDelegate(int n);

    void Foo(int n)
    {
        Console.WriteLine("n = {0}", n)
    }

    static void Main(string[] args)
    {
        MyDelegate d = new MyDelegate(Foo);
        d += Foo; // add Foo again

        d.Invoke(3); // Foo is invoked twice as Foo appears two times in invocation list

    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我查看MSDN Delegate时,MulticastDelegate我找不到+ =运算符的任何定义.它是如何起作用的?自动生成编译魔术?

Jon*_*eet 41

它不是委托类型本身的运算符,用IL术语 - 它是在语言规范中定义的,但你不会使用反射找到它.编译器将其转换为调用Delegate.Combine.反向操作,使用--=使用Delegate.Remove.

至少,当C#以.NET为目标时,它就是如何实现的,因为它几乎总是如此.理论上,这是特定于环境的 - 语言规范不要求编译器使用Delegate.CombineDelegate.Remove,并且不同的环境可能没有这些方法.

从C#5规范,第7.8.4节(补充):

+当两个操作数都是某种委托类型时,二元运算符执行委托组合D.(如果操作数具有不同的委托类型,则会发生绑定时错误.)如果第一个操作数是null,则操作的结果是第二个操作数的值(即使它也是null).否则,如果第二个操作数是null,则操作的结果是第一个操作数的值.否则,操作的结果是一个新的委托实例,在调用时,调用第一个操作数,然后调用第二个操作数.有关委托组合的示例,请参见§7.8.5和§15.4.由于System.Delegate不是委托类型,+因此未定义运算符.

  • @jensa 如果这是您对“编译器魔术”的定义,那么许多功能都是编译器魔术。例如 `==` 没有在 System.Object 上定义,但是语言定义了这样一个操作符。 (2认同)
  • @mikez:我认为区分语言指定的运算符是完全合理的 - 包括您提到的引用相等性 `==`,以及字符串连接 - 以及那些由库提供的运算符,例如 `DateTime +(DateTIme,时间跨度)`。 (2认同)