我知道 + = 运算符会将方法添加到由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
}
}
但是,当我查看MSDN Delegate,MulticastDelegate时,我无法找到 + = 运算符的任何定义。它是如何起作用的?自动生成编译器魔术?
答案 0 :(得分:36)
它不是委托类型本身的运算符,用IL术语 - 它是在语言规范中定义的,但你不会使用反射找到它。编译器将其转换为对Delegate.Combine
的调用。使用-
或-=
的反向操作使用Delegate.Remove
。
至少,这就是当C#以.NET为目标时的实现方式,因为它几乎总是如此。从理论上讲,这是特定于环境的 - 语言规范不要求编译器使用Delegate.Combine
或Delegate.Remove
,而不同的环境可能没有这些方法。
从C#5规范,第7.8.4节(补充):
当两个操作数都属于某个委托类型
+
时,二进制D
运算符会执行委托组合。 (如果操作数具有不同的委托类型,则会发生绑定时错误。)如果第一个操作数是null
,则操作的结果是第二个操作数的值(即使它也是null
})。否则,如果第二个操作数是null
,则操作的结果是第一个操作数的值。否则,操作的结果是一个新的委托实例,在调用时,调用第一个操作数,然后调用第二个操作数。有关委托组合的示例,请参见§7.8.5和§15.4。由于System.Delegate
不是委托类型,因此未为其定义运算符+
。
答案 1 :(得分:3)
与Int32
,String
等相同。+
运算符由语言隐式定义。
您可以查看Delegate
,MulticastDelegate
,Int32
等的源代码。operator +
没有重载,这就是为什么它没有出现在MSDN文档。
从C#语言规范,第7.8.4节:
下面列出了预定义的附加运算符。
(...)
•代表组合。每个委托类型都隐式提供以下预定义运算符,其中D是委托类型:
D operator +(D x, D y);
简单类型和委托之间存在差异。 C#语言规范不要求使用System.Delegate
4.2.7委托类型
委托是指引用一种或多种方法的数据结构。对于实例方法,它还引用它们对应的对象实例。 C或C ++中委托的最接近的等价物是函数指针,但是函数指针只能引用静态函数,委托可以引用静态和实例方法。在后一种情况下,委托不仅存储对方法入口点的引用,还存储对要调用该方法的对象实例的引用。 委托类型在§15中描述。
请注意,那里没有提到System.Delegate
。将它与4.1.4简单类型进行比较:
C#提供了一组称为简单类型的预定义结构类型。简单类型通过保留字标识,但这些保留字只是System命名空间中预定义结构类型的别名,如下表所示。
保留字别名类型
sbyte System.SByte
byte System.Byte
简短的System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
浮动System.Single
double System.Double
bool System.Boolean
decimal System.Decimal
或4.2.4节字符串类型
(...)
关键字字符串只是预定义类System.String的别名。
因此,为Delegate.Combine
的委托解析+运算符是.NET框架中C#编译器的实现细节。