文档介绍:第12章委托和事件
委托(delegate)是C#的特有的成分,delegate又被译为代表、代理、指代等。委托的功能类似于C或C++中的函数指针,但是委托是一种特殊的对象,与函数指针相比,委托有更多的功能,并且保持了C#的面向对象和类型安全的先进性。
事件(event)是对象之间通信的重要环节,也是事件驱动式应用程序的关键内容。在Window窗体应用程序、Web应用程序等系统中,事件和委托往往配合工作,相得益彰。
委托
运用数组类型可以将同一种类型的数据组织起来;运用多态技术可以把同一基类的派生类对象组织起来,委托也有这样的功能,委托可以将具有相同参数列表和返回类型的方法组织起来。委托主要有两个用途:方法回调和事件处理。
委托声明和委托对象
声明委托的格式如下:
特性修饰符 delegate 返回类型委托类型名(参数列表);
其中:特性、修饰符和参数列表是可选项;允许使用的修饰符有:new、public、internal、protected和private。
用关键字delegate声明的委托是一个类,这样的语法现象类似于用关键字class声明一个自定义的类。委托类型名、返回类型和参数列表共同构成一个委托的签名。也是区分不同委托的依据。
引例
声明委托类型
委托对象
创建委托对象就是实例化一个委托,其格式为:
委托对象= new 委托名(关联方法);
其中,参数是关联方法名,是被封装的方法,对于静态方法,委托对象封装要调用的方法;对于实例方法,委托对象同时封装一个实例和该实例上的一个方法。委托对象封装方法时并不论该方法属于什么类,只要该方法的参数列表和返回类型满足条件即可。
声明委托类和创建委托对象也可以用一句语句同时完成。
调用委托
调用委托需要用委托对象名和实参列表,与调用一般方法的格式没有差别。
在使用术语方面,通常不区分委托对象和委托的调用形式,都简称为委托。
委托封装了方法,委托中包含的是方法的引用。委托允许在执行时传入方法名,动态地决定要调用的方法,调用委托时才知道委托中包含的方法名。
委托的多播(组合)
委托的多播又称为委托组合。委托可以封装更多的方法,方法可以加入到委托中,也可以从委托中移除,这样的特点是一般函数指针所不可能具备的。
一个委托封装多个方法以后,调用委托对象就是调用其中所有的方法,这些被封装的方法又称为调用列表。调用列表可以包含重复的方法。在调用期间,委托按方法出现在调用列表中的顺序来调用方法。委托试图调用其调用列表中的每个方法,而重复方法在调用列表中出现一次就调用一次。
当委托所调用的方法包含返回值时,委托返回调用列表中最后一个方法的返回值。当方法中包含由引用传递的参数时,该参数的最终值就是调用列表中每个方法的结果,这些方法依次执行并更新参数的值。
可以用运算符“+”号将方法加入到调用列表中;用运算符“-”号将已经在调用列表中的方法从调用列表中移除。
Delegate和MulticastDelegate类型简介
Delegate和MulticastDelegate类型表示委托,其原型分别为:
public abstract class Delegate : ICloneable, Iserializable
abstract class MulticastDelegate extends Delegate
Delegate是可复制可序列化的抽象类,而MultiDelegate是Delegate的派生类。它们本身不是委托类型,不能派生新类型,而是由系统和编译器通过关键字delegate来产生委托类型,但是产生的委托类型又都继承Delegate类型。
属性
Delegate和MulticastDelegate有两个只读的公共属性Method和Target。
当委托关联实例方法时,Method存储着方法入口点的引用,Target存储目标对象的引用,因为实例方法必须由实例来引用,方法所用到的数据必须与特定对象有关,所以目标对象不能为空。
如果委托关联的是静态方法,Method存储的是该方法入口点的引用;而Target则为空引用null。
如果所调用的方法引发异常,则方法停止执行,并将异常向回传递给委托的调用方,且不再调用调用列表中其余的方法。捕捉调用方的异常并不改变此行为。
相等性
Delegate和MulticastDelegate都重写了相等操作符==和不等操作符!=,对于委托的相对性规定如下:
如果两个委托关联的两种方法都是静态方法,并且关联同一类中同一方法,则这些方法被视为相等,这些目标也被视为相等;