委托和类、结构一样,是类型。 事件和方法、属性一样,是类或结构的成员。 所以委托声明是在类前面,而事件声明是在类或结构内部。 1 发布者和订阅者 事件的工作过程可以用“发布者/订阅者”模式来理解。 发布者:发布某个事件的类或结构;订阅者:订阅事件,并在事件发生时得到通知的类或结构;事件处理程序,在发布者触发事件时执行的程序,可以定义在事件所在的类或结构中。 2 事件源代码几部分组成 委托类型声明 事件声明 当声明的事件为public时称为发布了事件 事件订阅 事件处理程序 触发事件 3 事件声明
event前面也可以加static关键字,事件声明为静态的。 2 订阅事件 使用+=运算符来订阅事件,运算符的右边可以是实例方法名称、静态方法名称、匿名方法、Lambda表达式。 3 触发事件 示例代码: delegatevoidHanlder1();//声明一个委托Hanlder1 classIncrementer // 发布者:发布一个事件 并在适当的时候触发 { publiceventHanlder1 CountedADozen;//声明事件并发布 publicvoid DoCount() { for (int i = 1; i < 100; i++) { if (i % 12 == 0 && CountedADozen != null) { CountedADozen();//触发事件 } } } } classDozen//订阅者:来确认这个事件触发时干什么 { publicint DozensCount { get; privateset; } public Dozen(Incrementer increment) { DozensCount = 0; increment.CountedADozen += IncrementDozensCount;//订阅事件 } void IncrementDozensCount()//事件处理程序 { DozensCount++; } } staticvoid Main() { Incrementer incrementer = newIncrementer(); Dozen dozenCounter = newDozen(incrementer); incrementer.DoCount(); Console.WriteLine("Number of dozen={0}", dozenCounter.DozensCount); } 代码中CountedADozen != null,是判断事件成员本身是否保存了需要被调用的事件处理程序。 CountedADozen();调用事件,和调用方法一样,只是名称是事件名称,参数列表必须和事件的委托类型相匹配。 class Incrementer为发布者类 class Dozen 为订阅者类 4 标准事件用法 .NET框架提供了事件使用的标准模式:使用EventHandler。 EventHandler是系统system命名空间声明的专门用于事件的委托类型。其声明如下: public delegate void EventHandler(object sender, EventArgs e); 该委托类型有两个参数,第一参数是触发事件的对象,第二个参数EventArgs类的对象,这个对象不能传递数据,需要传递数据需要定义新的派生类。 使用标准事件: classIncrementer { public event EventHandler CountedADozen;//使用系统定义的EventHandler委托来声明事件 publicvoid DoCount() { for (int i = 1; i < 100; i++) { if (i % 12 == 0 && CountedADozen != null) { CountedADozen(this,null);//触发事件时,和调用方法类似, 传递委托EventHandler的参数 } } } } classDozen { publicint DozensCount { get; privateset; } public Dozen(Incrementer increment) { DozensCount = 0; increment.CountedADozen += IncrementDozensCount; } void IncrementDozensCount(object source,EventArgs e)//事件处理程序的签名 必须和委托的签名匹配 { DozensCount++; } } 5 通过扩展EventArgs来传递数据 方法:定义一个EventArgs的派生类,使得该派生类能够保存我们需要传入的变量,再使用泛型版本的委托EventHandler<TEventArgs>来定义事件。 标准事件委托的泛型版本声明: public delegate voidEventHandler<TEventArgs>(object sender, TEventArgs e); 示例代码: publicclassIncrementerEventAgrs : EventArgs//重新自定义一个EventArgs的派生类 { publicint IterationCount { get;set;}//定义一个变量 } classIncrementer { publiceventEventHandler<IncrementerEventAgrs> CountedADozen;//使用自定义的泛型委托 来声明事件 publicvoid DoCount() { IncrementerEventAgrs args = newIncrementerEventAgrs(); for (int i = 1; i < 100; i++) { if (i % 12 == 0 && CountedADozen != null) { args.IterationCount = i; CountedADozen(this,args);//传递参数 } } } } classDozen { publicint DozensCount { get; privateset; } public Dozen(Incrementer increment) { DozensCount = 0; increment.CountedADozen += IncrementDozensCount; } void IncrementDozensCount(object source, IncrementerEventAgrs e) { Console.WriteLine("Incrementer at iteration:{0} in {1}", e.IterationCount, source.ToString()); DozensCount++; } } 6 移除事件处理程序 使用-=运算符 移除列表中该处理程序的最后一个实例 7 事件访问器 add remove