委托

委托是寻址方法的.NET版 本。在C++中,函数指针只不过是一个指向内存位置的指针,它不 是类型安全的。我们无法判断这个指针实际指向什么,像参数和返回类型等项就更无从知晓了。 而,NET委托完全不同,委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对 方法的引用,也可以包含对多个方法的引用。 

在C和 C++中,只能提取函数的地址,并作为一个参数传递它。C没有类型安全性。可以把任 何函数传递给需要函数指针的方法。但是,这种直接方法不仅会导致一些关于类型安全性的问题 , 而且没有意识到:在进行面向对象编程时,几乎没有方法是孤立存在的,而是在调用方法前通常需 要与类实例相关联。所以.NET Framework在 语法上不允许使用这种直接方法。如果要传递方法,就必须把方法的细节封装在一种新类型的对象中,即委托。委托只是一种特殊类型的对象,其特殊之 处在于,我们以前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址。

声明委托

首先必须定义要使用的委托,对于委托,定义它就是告诉编译器这种类型的委托表示哪种类 型的方法。然后,必须创建该委托的一个或多个实例。编译器在后台将创建表示该委托的一个类。 

定义委托的语法如下 :

delegate void IntMethodInvoker(int x);

在这个示例中,定义了一个委托 IntMethodInvoker,并 指定该委托的每个实例都可以包含一个 方法的引用,该方法带有一个 血 参数,并返回void。理解委托的一个要点是它们的类型安全性非 常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。

其语法类似于方法的定义,但没有方法体,定义的前面要加上关键字 delegate。 因为定义委托基 本上是定义一个新类,所以可以在定义类的任何相同地方定义委托,也就是说,可以在另一个类的内部定义,也可以在任何类的外部定义,还可以在名称空间中把委托定义为顶层对象。根据定义的可见 性,和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public、private、protected等。

使用委托

private delegate string GetString();

static void Main()

{

  int x = 40;

  GetString firstStringMethod = new GetString(x.ToString);

  Console.WriteLine("String is {0}", firstStringMethod());

}

在这段代码中,实例化了类型为GetString吧 的一个委托,并对它进行初始化,使它引用整型变 量x的 ToString()方法。在C#中 ,委托在语法上 `总 是接受一个参数的构造函数,这个参数就是委托引 用的方法。这个方法必须匹配最初定义委托时的签名。所以在这个示例中,如果用不带参数并返回 一个字符串的方法来初始化firstStringMethod变量,就会产生一个编译错误。 注意,因为int.ToString()是一个实例方淑不是静态方法),所以需要指定实例⑺和方法名来正确地初始化委托。

为了减少输入量,只要需要委托实例,就可以只传送地址的名称。这称为委托推断。只要编译器可以把委托实例解析为特定的类型,这个C#特性就是有效的。 下面的示例用GetString委托的一 个新实例初始化GetString类型的frstStringMethod变量 :

GetString firstStringMethod = new GetString(x.ToString);

只要用变量X把方法名传送给变量firstStringMethod,就可以编写出作用相同的带码:

GetString firstStringMethod = x.ToString;

多播委托

前面使用的每个委托都只包含一个方法调用。调用委托的次数与调用方法的次数相同。如果要 调用多个方法,就需要多次显式调用这个委托。但是,委托也可以包含多个方法。这种委托称为多 播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回奶⒒ 否则,就只能得到委托调用的最后一个方法的结果。

class Program

{

  static void Main()

  {

    Action<double>operation = MathOperation.MultiplyByTwo;

    operation +=MathOperation.Square; 

  }

在前面的示例中,因为要存储对两个方法的引用,所以实例化了一个委托数组。而这里只是在 同一个多播委托中添加两个操作。多播委托可以识别运算符“+"和"+="。

如果正在使用多播委托,就应知道对同一个委托调用方法链的顺序并未正式定义。因此应避免 编写依赖于以特定顺序调用方法的代码。 通过一个委托调用多个方法还可能导致一个大问题。多播委托包含一个逐个调用的委托集合。如 果通过委托调用的其中一个方法抛出一个异常,整个迭代就会停止。

原文地址:https://www.cnblogs.com/miffylf/p/4026720.html