Event 事件
- 使用委托的时候,通常会出现两个角色,一个广播者,一个订阅者
广播和订阅
- 使用委托的时候,通常会出现两个角色,一个广播者,一个订阅者
- 广播者这个类型包含一个委托字段,广播者通过调用委托来决定什么时候进行广播。
- 订阅者是方法目标的接收者,订阅者可以决定何时开始或结束监听,方式是通过在委托上调用+=和-=。
- 一个订阅者不知道和不干扰其它的订阅者。
Event 事件
事件就是将上述模式正式化的一个语言特性。
事件是一种结构,为了实现广播者/订阅者模型,它只暴露了所需的委托特性的部分子集。
事件的主要目的就是防止订阅者之间互相干扰。
声明事件
最简单的声明事件的方式就是在委托前面加上event关键字
内外区别对待
- Broadercaster类型里面的代码拥有对PriceChanged的完全访问权,在这里就可以把它当作委托。
- 而Broadercaster类型之外的代码只能对PriceChanged这个event执行+=或-=操作。
事件在内部是如何工作的?
- 首先,编译器把事件的声明翻译成类似下面的代码:
- add 和 remove 关键字代表着显式的事件访问器,有点像属性访问器。
- 然后编译器会查看Broadcaster内部对PriceChanged的引用,如果不是+=或-=的操作,那就直接把它们定向到底层的委托字段priceChanged。
- 第三点,编译器把作用在event上的+=和-=操作翻译成调用add或remove访问器。
标准的事件模式
- 为编写事件,.NET定义了一个标准的模式
- System.EventArgs,一个预定义的框架类,除了静态的Empty属性之外,它没有其它成员。
- EventArgs是为事件传递信息的类的基类。
例子
通常是根据所含有的信息进行命名,而不是所使用的事件
通常通过属性或只读字段来暴露数据
为事件选择或定义委托
- 返回类型是void;
- 接收两个参数,第一个参数类型是object,第二参数类型是EventArgs的子类。第一个参数表示事件的广播者,第二个参数包含需要传递的信息;
- 名称必须以EventHandler结尾。
System.EventHandler
- Framework定一了一个范型委托System.EventHandler
,它满足上述规则。
针对选择的委托定义事件
可触发事件的protected virtual方法
- 方法名必须和事件一致,前面再加上On,接收一个EventArgs参数
- 多线程的场景下,你需要在测试或调用前,把委托赋给一个临时变量,来避免线程安全相关的错误:
- 在C#6之后,可以这样写:
非范型的EventHandler
- 当事件不携带多余信息的时候,可以使用非范型的EventHandler委托。
- EventArgs.Empty属性
事件访问器
- 事件访问器是事件的+=和-=函数的实现。
public event EventHandler PriceChanged;
编译器会把它转化为:
- 一个私有的委托字段
- 一对公共的事件访问器函数(add_PriceChanged和remove_PriceChanged),这两个函数的实现会把+=和-=操作交给私有的委托字段。
- 也可以显式的定义事件访问器
显式定义的事件访问器
- 当事件访问器仅仅是另一个广播事件的类的中继。
- 当类暴露大量event,但是大部分时候都只有少数的订阅者存在。
- 显式实现一个声明了事件的接口。
事件修饰符
- virtual,可以被重写;abstract,sealed,static。