委托和事件

什么是委托

委托是持有一个或多个方法的对象。正常情况下我们不会想要“执行”一个对象,但委托于典型的对象不同。可以执行委托,这时委托会执行它所“持有”的方法。委托和类一样,是一种用户自定义的类型。但类表示的是数据和方法的集合,而委托则持有一个或多个方法,以及一系列预定义操作。

使用委托

(1)声明一个委托类型。

 delegate 返回类型 类型名称(参数);

(2)使用该委托类型声明一个委托变量。

(3)创建委托类型的对象,把它赋值给委托变量。新的委托对象包括指向某个方法的引用,这个方法和第一步定义的签名和返回类型一致。

(4)使用委托

委托是一个包含有序方法列表的对象,这些方法具有相同的签名和返回类型。

委托保存的方法可以来自任何类或结构

(1)委托的返回类型。

(2)委托的签名(包括ref和out修饰符)。

(3)调用列表中的方法可以是实例方法也可以是静态方法。

(4)在调用委托的时候,会执行器调用列表中所有方法。

委托是引用类型,委托变量中保存的是对象方法的引用地址。

创建委托的方式

(1)委托类型 变量名 = new 委托类型(方法);

(2)委托类型 变量名 = 方法;

委托可以保存静态方法也可以是实例方法

委托是不可变的,所有每次改变都是创建新的对象和引用地址

组合委托:将委托调用雷彪整合。

例如:委托类型 组合委托变量= 委托变量A+委托变量C;

委托方法添加

委托变量 += 方法;

委托方法移除

委托变量 -= 方法;

判断委托是否为null

if(委托变量!=null){

}

委托的调用

委托()/委托(参数)

匿名方法

当一个方法只使用一次时,就用匿名方法,匿名方法是在初始化委托时内联声明的方法。


使用匿名方法

(1)声明委托变量时作为初始化表达式。

(2)组合委托时在赋值语句的右边

(3)为委托增加事件时在赋值语句的右边

语句:delegate(参数){方法体}

返回类型

匿名方法不会显示声明返回值。然而,实现代码的行为必须通过返回一个类型上与委托的返回类型相同的值来匹配委托的返回类型。如果委托void类型有返回值,匿名方法就不能返回值。


参数

除了数组参数,匿名方法的参数列表必须在如下3方面与委托匹配:

(1)参数数量

(2)参数类型及位置

(3)修饰符

通过使圆括号为空或省略号来简化匿名方法的参数列表,但是必须满足一下两个条件:

(1)委托的参数列表不包含任何out参数。

(2)匿名方法不适用任何参数。


params参数

如果委托声明的参数列表包含了params参数,那么匿名方法的参数列表就忽略params关键字



变量和参数的作用域

用在匿名方法实现得代码中的外部变量称为方法扑获

事件

发布者/订阅者模式(publisher/subscriber pattern)

发布者类定义了一系列程序的其他部位可能感兴趣的事件。其他类可以“注册”以便在这些事件发生时发布者可以通知它们。这些订阅者类通过向发布者提供一个方法来“注册”以获取通知。当发生事件时,发布者“触发事件”,然后执行订阅者提交的所有事件。


发布者(publisher)发布某个事件的类或结构,其他类可以砸该事件发生时得到通知。

订阅者(subscriber)注册并在事件发生时得到通知的类或结构。

事件处理程序(event handler)由订阅者注册到事件的方法,在发布者触发事件时执行。事件处理程序方法可以定义在事件所在的类或结构中,也可以定义在不停的类或结构中。

触发(raise)事件 调用(invoke)或触发(fire)事件的术语。当事件触发时,所有注册到它的方法都会被一次调用。

事件时专门用于某种特殊用途的简单委托。


事件的私有委托需要注意:

(1)事件提供了对它的私有控制委托的结构化访问。无法直接访问委托。

(2)事件中可用的操作比委托要少,对于事件我们只可以添加,删除或调用事件处理程序。

(3)事件被触发时,它调用委托来依次调用调用列表中的方法。

只有+=和-=运算符在事件框的左边。因为,它们是事件唯一允许的操作(除了事件本身)


事件使用

委托类型声明: 事件和事件处理程序必须有共同的前面和返回类型,它们通过委托类型靖西描述。

事件处理程序声明:订阅者类中会在事件触发时执行的方法声明,它们不一定有显示的命名方法。

事件声明:发布者类必须声明一个订阅者类可以注册的事件成员,当声明的事件为public时,称为发布了事件。

事件注册:订阅者必须订阅事件才能在它被触发时得到通知。

触发事件的代码:发布者类中“触发”事件并导致调用注册的所有事件处理程序的代码。


声明事件

public (static) event EventHandler 事件名称
event :关键字
EventHandler :委托类型


事件是成员

事件时成员,不是类型。和方法、属性一样,事件时类或结构的成员。

特性:

1.由于事件是成员:

(1)我们不能在一段可执行代码中声明事件。

(2)它必须声明在类或结构中,和其他成员一样。

2.事件成员被隐式自动化为null

事件声明需要委托类型的名字,我们也可以声明一个委托类型或使用已存在的,如果我们声明一个委托类型,它必须指定事件保存的方法签名和返回类型。

订阅事件

订阅者向事件添加事件处理程序,对于一个要添加到事件的事件处理程序来说,它必须具有与事件的委托相同的返回类型和签名。

1.使用+=运算符来为事件增加事件处理程序,事件处理程序位于该运算符的右边。

2.事件处理程序的规范可以是一下任意一种:

(1)实例方法的名称;

(2)静态方法的名称;

(3)匿名方法;

(4)Lambda表达式



触发事件

事件成员本身只是保存了需要被调用的事件处理程序。如果事件没有被触发,什么都不会发生。我们需要确保在合适的时候有代码来做这些事情。

注意事项

1.在触发事件之前和null进行比较,从而查看是否包含事件处理程序,如果事件时null,则表示没有,不能执行。

2.触发事件的预防和调用方法一样:

(1)使用事件名称,后面跟的参数列表包含在圆括号中;

(2)参数列表必须与事件的委托类型相匹配。

标准事件的用法

使用使用的标准模式的根本就是System命名空间声明的EventHander委托类型。

该声明需要注意:

1.第一个参数用来保存触发事件的对象的引用。由于是object类型的,所有可以匹配任何类型的实例;

2.第二个参数用来保存状态信息,指明什么类型适用程序;

尽管EventArgs类实际上并不传递数据,但它是使用EventHandler委托模式的重要部分。不管参数使用的实际类型是什么,object类和EventArgs总是基类。

通过扩展EventArgs类来传递数据

为了向自己的事件处理程序的第二个参数传入数据,并且又符合标准惯例,声明一个派生自EventArgs的自定义类,它可以保存我们需要传入的数据。类的名称应该以EventArgs结尾。

public class IncrementerEventArgs:EventArgs{

public int IterationCount{get;set;};

}


移除事件处理程序

在用完了事件处理程序后,可以从事件中把它移除,利用-=运算符把事件处理程序从事件中移除。
p.SimpleEvent -= s.MethodB;




猜你喜欢

转载自blog.csdn.net/luochenlong/article/details/79065065