说我有一个代表
public delegate void StringLogging(string msg);
现在类 A 使用这个委托来提供自己的实现,也Class B
提供自己的实现。委托的调用列表StringLogging
包含两个相同的方法Class A
,一个用于 B 类,一个用于 B 类。委托如何知道哪个函数属于 A 类,哪个函数属于 B 类。
内部委托被实现为MultiCastDelegate
.
Delegate.GetInvocationList()
返回Delegate[]
与 main 关联的每个方法对应的返回值Delegate
。
Delegate.Method
是MethodInfo
有DeclaringType
。这DeclaringType
具有类是Class A
或Class B
其他类型的信息。
这在 C# 中被小心地隐藏了。但是委托构造函数有两个参数,一个对象和一个方法组引用。在 C++/CLI 语言中更容易看到,它没有相同的语法糖。例如,为按钮订阅 Click 事件如下所示:
this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
请注意第一个参数,即实现 button1_Click 方法的对象的对象引用。委托类型对该对象引用没有做任何特殊的事情,它只是存储它。基础字段是 Delegate.Target。稍后,当调用委托时,它会用于生成实例方法所需的同样隐藏的this引用。
C# 语言不允许相同的语法,编译器从您在构造函数中传递的方法组引用推断对象引用。这可以防止事故。请注意这种语法糖的价格,C# 程序员通常没有意识到订阅事件会保留对目标对象的引用。导致难以诊断的泄漏是一种常见的事故。
C++/CLI 中的显式语法允许 C# 中完全缺少的功能,它支持未绑定的委托。它不是特别有用,但它确实模拟了 C++ 中方法指针的工作方式。C++/CLI 没有采用 C# 糖的可能原因。