事件
大约 2 分钟
事件
发布者和订阅者
发布者:发布某个事件的类或结构,其他类可以在该事件发生时得到通知;
订阅者:注册并在事件发生时得到通知的类或结构;
事件处理程序:由订阅者注册到事件的方法,在发布者触发事件时执行;
触发事件:调用(invoke)、触发(fire)事件的术语;
事件的内涵
事件属于一种特殊用途的简单委托,事件包含了一个私有的委托;
事件提供了对它的私有委托的结构化访问;
事件只可以添加、删除、调用处理程序的简单操作;
// 声明委托
delegate void Handler();
// 发布者
class Incrementer
{
// 创建事件并发布
public event Handler CountedADozen;
public void DoCount()
{
for(int i=1;i<100;i++)
if(i%12 == 0 && CountedADozen != null)
CountedADozen(); // 每增加12个计数触发事件一次
}
}
// 订阅者
class Dozens
{
public int DozensCount{get;private set;}
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
// 订阅事件
incrementer.CountedADozen += IncrementDozensCount;
}
// 事件处理程序
void IncrementDozensCount()
{
DozensCount++;
}
}
标准事件 EventHandler
public delegate void EventHandler ( object sender, EventArgs e );
object sender 用来保存触发事件的对象的引用,可以匹配任何类型的实例;
EventArgs e 用来保存状态信息,不能传递任何数据,通常在不需要传达数据的事件处理程序时忽略;
如果需要传递数据,需要设计一个派生自 EventArgs 的类,使用合适的字段来保存数据;
// 声明一个派生自EventArgs的类,类名一般以EventArgs结尾; public class ClassNameEventArgs : EventArgs { … } public class Publisher { // 使用泛型委托 EventHandler < 派生类名 > 发布事件; public event EventHandler < ClassNameArgs > EventName ; // 使用派生类来触发事件传递参数; ClassNameEventArgs args = new ClassNameEventArgs ( ) ; public void Do() { EventName ( this , args ) ; } } public class Subscriber { // 在订阅者类中直接使用派生类属性 void Function ( object sourse , ClassNameEventArgs e ) { var tmp = e.PropertyName ; } }
事件访问器
声明事件访问器 add 和 remove ,类似于声明属性;
声明了事件访问器后,事件不包含任何内嵌委托对象,必须实现自己的机制来存储和移除事件注册的方法;
事件访问器不能使用或包含返回值的 return 语句;
public event EventHandler CounterADozen { add{...} // 执行 += 运算符的代码 remove{...} // 执行 -= 运算符的代码 }