[转载]C#委托和事件(Delegate、Event、EventHandler、EventArgs)

时间:2022-04-13 03:42:00

标签:

原文链接: 14.1、委托

当要把方法作为实参传送给其他方法的形参时,形参需要使用委托。委托是一个类型,是一个函数指针类型,这个类型将该委托的实例化对象所能指向的函数的细节封装起来了,即规定了所能指向的函数的签名,也就是限制了所能指向的函数的参数和返回值。当实例化委托的时候,委托对象会指向某一个匹配的函数,实质就是将函数的地址赋值给了该委托的对象,然后就可以通过该委托对象来调用所指向的函数了。利用委托,程序员可以在委托对象中封装一个方法的引用,然后委托对象作为形参将被传给调用了被引用方法的代码,而不需要知道在编译时刻具体是哪个方法被调用。

一般的调用函数,我们都不会去使用委托,因为如果只是单纯的调用函数,使用委托更麻烦一些;但是如果想将函数作为实参,传递给某个函数的形参,那么形参就一定要使用委托来接收实参,一般使用方法是:在函数外面定义委托对象,并指向某个函数,再将这个对象赋值给函数的形参,形参也是该委托类型的对象变量,函数里面再通过形参来调用所指向的函数。

14.1.1、定义委托

语法如下

delegate  result-type   Identifier ([parameters]);

说明:

result-type:返回值的类型,和方法的返回值类型一致

Identifier:委托的名称

parameters:参数,要引用的方法带的参数

小结

当定义了委托之后,该委托的对象一定可以而且也只能指向该委托所限制的函数。即参数的个数、类型、顺序都要匹配,返回值的类型也要匹配。

因为定义委托相当于是定义一个新类,所以可以在定义类的任何地方定义委托,既可以在一个类的内部定义,那么此时就要通过该类的类名来调用这个委托(委托必须是public、internal),也可以在任何类的外部定义,那么此时在命名空间中与类的级别是一样的。根据定义的可见性,可以在委托定义上添加一般的访问修饰符:当委托定义在类的外面,那么可以加上public、internal修饰符;如果委托定义到类的内部,那么可以加上public、 private、 protected、internal。一般委托都是定义在类的外面的。

14.1.2、实例化委托

Identifier  objectName  =  new  Identifier( functionName);

实例化委托的实质就是将某个函数的地址赋值给委托对象。在这里:

Identifier :这个是委托名字。

objectName :委托的实例化对象。

functionName:是该委托对象所指向的函数的名字。对于这个函数名要特别注意:定义这个委托对象肯定是在类中定义的,那么如果所指向的函数也在该类中,不管该函数是静态还是非静态的,那么就直接写函数名字就可以了;如果函数是在别的类里面定义的public、

internal,但是如果是静态,那么就直接用类名.函数名,如果是非静态的,那么就类的对象名.函数名,这个函数名与该对象是有关系的,比如如果函数中出现了this,表示的就是对当前对象的调用。

14.1.3、委托推断

C# 2.0用委托推断扩展了委托的语法。当我们需要定义委托对象并实例化委托的时候,就可以只传送函数的名称,即函数的地址:

Identifier  objectName  =  functionName;

这里面的functionName与14.1.2节中实例化委托的functionName是一样的,没什么区别,满足上面的规则。

C#编译器创建的代码是一样的。编译器会用objectName检测需要的委托类型,因此会创建Identifier委托类型的一个实例,用functionName即方法的地址传送给Identifier的构造函数。

注意:

不能在functionName后面加括号和实参,然后把它传送给委托变量。调用方法一般会返回一个不能赋予委托变量的普通对象,除非这个方法返回的是一个匹配的委托对象。总之:只能把相匹配的方法的地址赋予委托变量。

委托推断可以在需要委托实例化的任何地方使用,就跟定义普通的委托对象是一样的。委托推断也可以用于事件,因为事件基于委托(参见本章后面的内容)。

14.1.4、匿名方法

到目前为止,要想使委托工作,方法必须已经存在。但实例化委托还有另外一种方式:即通过匿名方法。

用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化委托时,就有区别了。下面是一个非常简单的控制台应用程序,说明了如何使用匿名方法:

using System;

namespace Wrox.ProCSharp.Delegates

{

class Program

{

delegate string DelegateTest(string val);

static void Main()

{

string mid = ", middle part,";

//在方法中定义了方法

DelegateTest  anonDel = delegate(string param)

      {

        param += mid;

        param += " and this was added to the string.";

        return param;

      };

Console.WriteLine(anonDel("Start of string"));

}

}

}