通用类型系统中的委托
更新:2007 年 11 月
运行时支持称为委托的引用类型,其作用类似于 C++ 中函数指针的用途。与函数指针不同,委托是安全、可验证和类型安全的。委托类型可以表示任何具有兼容签名的方法。函数指针只能表示静态函数,委托则可以同时表示静态方法和实例方法。委托用于 .NET Framework 中的事件处理程序和回调函数。
![]() |
---|
公共语言运行时不支持全局方法序列化,因此不能使用委托来执行其他应用程序域中的全局方法。 |
所有委托从 MulticastDelegate(继承自 Delegate)继承。C#、Visual Basic 和 C++ 语言不允许从这些类型继承,而是提供了用于声明委托的关键字。
除了继承的方法,公共语言运行时还为委托类型提供两个特殊方法:BeginInvoke 和 EndInvoke。有关这些方法的更多信息,请参见 使用异步方式调用同步方法。
由于委托从 MulticastDelegate 继承,因此委托具有一个调用列表,其中列出了委托表示的方法,在调用委托时将执行该列表中的方法。列表中的所有方法接收调用委托时提供的参数。
![]() |
---|
没有为在调用列表中包含多个方法的委托(即使委托具有返回类型)定义返回值。 |
在许多情况下(例如回调方法),一个委托只表示一个方法,您需要采取的唯一操作是创建委托并调用它。
对于表示多个方法的委托,.NET Framework 提供了 Delegate 和 MulticastDelegate 委托类的方法以支持如下操作:将方法添加到委托的调用列表(Delegate.Combine 方法)、移除方法(Delegate.Remove 方法)、获取调用列表(Delegate.GetInvocationList 方法)。
![]() |
---|
不需要将这些方法用于 C#、C++ 和 Visual Basic 中的事件处理程序委托,因为这些语言为添加和移除事件处理程序提供了语法。 |
委托可以表示 static(在 Visual Basic 中为 Shared)或实例方法。通常,当委托表示实例方法时,实例与方法一起绑定到委托。例如,事件处理程序委托在其调用列表中可以有三个实例方法,每个方法有一个对方法所属对象的引用。
在 .NET Framework 2.0 版中,还能够为实例方法创建开放式委托。实例方法有一个隐式实例参数(在 C# 中由 this 表示,在 Visual Basic 中由 Me 表示),它可以由公开此隐藏参数的委托类型表示。也就是说,委托类型必须在其形参表的开头有一个额外参数,该参数的类型必须与方法所属的类的类型相同。与此相反的情形也受支持,因此还可以绑定静态方法的第一个参数。
![]() |
---|
对于委托构造函数,开放式实例委托和封闭式静态委托的创建不受 Visual Basic、C++ 或 C# 的直接支持。相反,使用指定 MethodInfo 对象(例如 Delegate.CreateDelegate(Type, Object, MethodInfo, Boolean))的 Delegate.CreateDelegate 方法重载之一。 |
在 .NET Framework 2.0 版中,委托的参数类型和返回类型必须与委托表示的方法的参数类型和返回类型兼容,这些类型不必完全匹配。
![]() |
---|
在 .NET Framework 1.0 和 1.1 版中,这些类型必须完全匹配。 |
如果委托参数的类型比方法参数的类型更严格,则委托的参数与方法的对应参数兼容,因为这可以确保传递给委托的参数可以安全地传递给方法。
同样,如果方法的返回类型比委托的返回类型更严格,则委托的返回类型与方法的返回类型兼容,因为这可以确保方法的返回值可以安全地强制转换为委托的返回类型。
例如,具有类型为 Hashtable 的参数和 Object 返回类型的委托可以表示具有类型为 Object 的参数和类型为 Hashtable 的返回值的方法。
有关更多信息及示例代码,请参见 Delegate.CreateDelegate(Type, Object, MethodInfo)。
每个委托有一个 BeginInvoke 方法和一个 EndInvoke 方法,使用前者可以异步调用委托,而使用后者可以稍后清理资源。为每个委托类型自动生成了这些方法。当使用 BeginInvoke 方法调用委托时,该委托表示的方法在属于 ThreadPool 的线程上执行。
有关更多信息及示例代码,请参见 使用委托进行异步编程。