在C#中声明委托
首先定义要使用的委托,对于委托,定义它就是告诉编译器这种类型的委托代表了哪种类型的方法,然后创建该委托的一个或多个实例。
实际上,"定义一个委托"是指"定义一个新类"。委托实现为派生自基类System. Multicast Delegate的类,System.MulticastDelegate又派生自基类System.Delegate。C#编译器知道这个类,会使用其委托语法,因此我们不需要了解这个类的具体执行情况,这是C#与基类共同合作,使编程更易完成的另一个示例。
定义好委托后,就可以创建它的一个实例,以存储特定方法的细节。
此处,在术语方面有一个问题。类有两个不同的术语:"类"表示较广义的定义,"对象"表示类的实例。但委托只有一个术语。在创建委托的实例时,所创建的委托的实例仍称为委托。必须从上下文中确定委托的确切含义。
在C#中,委托在语法上总是带有一个参数的构造函数,这个参数就是委托引用的方法。这个方法必须匹配最初定义委托时的签名。
C# 2.0使用委托推断扩展了委托的语法。为了减少输入量,只要需要委托实例,就可以只传送地址的名称。这称为委托推断。只要编译器可以把委托实例解析为特定的类型,这个C#特性就是有效的。
委托推断可以在需要委托实例的任何地方使用。委托推断也可以用于事件,因为事件基于委托(参见本章后面的内容)。
委托的一个特征是它们的类型是安全的,可以确保被调用的方法签名是正确的。但有趣的是,它们不关心在什么类型的对象上调用该方法,甚至不考虑该方法是静态方法,还是实例方法。
提示:
给定委托的实例可以表示任何类型的任何对象上的实例方法或静态方法-- 只要方法的签名匹配于委托的签名即可。
多播委托
如果要调用多个方法,就需要多次显式调用这个委托。委托也可以包含多个方法。这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。
匿名方法
到目前为止,要想使委托工作,方法必须已经存在(即委托是用方法的签名定义的)。但使用委托还有另外一种方式:即通过匿名方法。匿名方法是用作委托参数的一个代码块。
表达式
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
delegate string DelegateTest(string val);
static void Main(string[] args)
{
string mid = ", middle part,";
//DelegateTest anonDel = param =>//表達式方法
DelegateTest anonDel = delegate(string param)//匿名方法
{
param += mid;
param += " and this was added to the string.";
return param;
};
Console.WriteLine(anonDel("Start of string"));
Console.ReadLine();
}
}
}
协变和抗变
返回类型协变
方法的返回类型可以派生于委托定义的类型。在下面的示例中,委托MyDelegate定义为返回DelegateReturn类型。赋予委托实例d1的方法返回DelegateReturn2类型,DelegateReturn2派生自DelegateReturn,因此满足了委托的需求。这称为返回类型协变。
参数类型抗变
语"参数类型抗变"表示,委托定义的参数可能不同于委托调用的方法。这里是返回类型不同,因为方法使用的参数类型可能派生自委托定义的类型。
事件
从接收器的角度讨论事件
事件接收器是指在发生某些事情时被通知的任何应用程序、对象或组件。当然,有事件接收器,就有事件发送器。发送器的作用是引发事件。