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