委托
delegate 是表示对具有特定参数列表和返回类型的方法的引用的类型。在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联。你可以通过委托实例调用方法。
委托用于将方法作为参数传递给其他方法。事件处理程序就是通过委托调用的方法。你可以创建一个自定义方法,当发生特定事件时,某个类(如 Windows 控件)就可以调用你的方法。下面的示例演示了一个委托声明:
public delegate int PerformCalculation(int x, int y);
可将任何可访问类或结构中与委托类型匹配的任何方法分配给委托。该方法可以是静态方法,也可以是实例方法。这样便能通过编程方式来更改方法调用,还可以向现有类中插入新代码。
注意:在方法重载的上下文中,方法的签名不包括返回值。但在委托的上下文中,签名包括返回值。换句话说,方法和委托必须具有相同的返回类型。
将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,对比较两个对象的方法的引用可以作为参数传递到排序算法中。由于比较代码在一个单独的过程中,因此可通过更常见的方式编写排序算法。
委托概述
委托具有以下属性:
- 委托类似于 C++ 函数指针,但它们是类型安全的。
- 委托允许将方法作为参数进行传递。
- 委托可用于定义回调方法。
- 委托可以链接在一起;例如,可以对一个事件调用多个方法。
- 方法不必与委托类型完全匹配。
- C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递来代替单独定义的方法。C# 3.0 引入了 Lambda 表达式,利用它们可以更简练地编写内联代码块。匿名方法和 Lambda 表达式(在某些上下文中)都可编译为委托类型。这些功能现在统称为匿名函数。
使用委托
委托是安全封装方法的类型,类似于 C 和 C++ 中的函数指针。与 C 函数指针不同的是,委托是面向对象的、类型安全的和可靠的。委托的类型由委托的名称确定。以下示例声明名为 Del 的委托,该委托可以封装采用字符串作为参数并返回 void 的方法:
public delegate void Del(string message);
委托对象通常通过提供委托将封装的方法的名称或使用匿名方法构造。对委托进行实例化后,委托会将对其进行的方法调用传递到该方法。调用方传递到委托的参数将传递到该方法,并且委托会将方法的返回值(如果有)返回到调用方。这被称为调用委托。实例化的委托可以按封装的方法本身进行调用。例如:
// Create a method for a delegate.
public static void DelegateMethod(string message)
{
System.Console.WriteLine(message);
}
// Instantiate the delegate.
Del handler = DelegateMethod;
// Call the delegate.
handler("Hello World");
委托类型派生自 .NET Framework 中的 Delegate 类。委托类型是封装的,它们不能派生出其他类,也不能从 Delegate 派生出自定义类。由于实例化的委托是一个对象,因此可以作为参数传递或分配给一个属性。这允许方法作为参数接受委托并在稍后调用委托。这被称为异步回调,是在长进程完成时通知调用方的常用方法。当以这种方式使用委托时,使用委托的代码不需要知道要使用的实现方法。功能类似于封装接口提供的功能。
回调的另一个常见用途是定义自定义比较方法并将该委托传递到短方法。它允许调用方的代码成为排序算法的一部分。以下示例方法使用 Del 类型作为参数:
public void MethodWithCallback(int param1, int param2, Del callback)
{
callback("The number is: " + (param1 + param2).ToString());
}
然后,你可以将上面创建的委托传递到该方法:
MethodWithCallback(1, 2, handler);
并将以下输出接收到控制台:
以抽象方式使用委托时,MethodWithCallback 不需要直接调用控制台,记住,其不必设计为具有控制台。 MethodWithCallback 的作用是简单准备字符串并将字符串传递到其他方法。由于委托的方法可以使用任意数量的参数,此功能特别强大。
当委托构造为封装实例方法时,委托将同时引用实例和方法。委托不知道除其所封装方法以外的实例类型,因此委托可以引用任何类型的对象,只要该对象上有与委托签名匹配的方法。当委托构造为封装静态方泣У |