type
status
date
slug
summary
tags
category
icon
password
Property
Aug 14, 2023 11:53 AM
事件的声明
事件的声明
- 完整声明
- 简略声明(字段式声明,field-like)
有了委托字段/属性,为什么还需要事件
- 为了程序的逻辑更加“有道理”、更加安全,谨防“借刀杀人”
所以事件的本质是委托字段的一个包装器
- 这个包装器对委托字段的访问起限制作用,相当于一个“蒙版”
- 封装(encapsulation)的一个重要功能就是隐藏
- 事件对外界隐藏了委托实例的大部分功能,仅暴露添加/移除事件处理器的功能
- 添加/移除事件处理器的时候可以直接使用方法名,这是委托实例所不具备的功能
用于声明事件的委托类型的命名约定
- 用于声明Foo事件的委托,一般命名为FooEventHandler(除非是一个非常通用的事件约束)
- FooEventHandler委托的参数一般有2个(由Win32 API演化而来,历史悠久)
- 第一个是object类型,名字为sender,实际上就是事件的拥有者、事件的source
- 第二个是EventArgs类的派生类,类名一般为FooEventArgs,参数名为e。也就是前面讲过的事件参数
- 虽然没有官方的说法,但我们可以把委托的参数列表看做是事件发生后给事件响应者的“事件消息”
- 触发Foo事件的方法一般命名为OnFoo,即“因何引发”、“事出有因”
- 访问级别为protected,不能为public,不然又成了可以“借刀杀人”了
事件的命名约定
- 常有时态的动词或者动词短语
- 事件拥有者“正在做”什么事情,用进行时;事件拥有者“做完了”什么事情,用完成时
事件成员不论从表层约束还是底层实现,都是依赖委托的。
事件声明完整格式
简略声明
"借刀杀人"的案例
public的委托字段有可能在外部被其他调用、误用,所以要用这种形式:public event OrderEventHandler Order;
使用内部的EventHandler
一定要判断,方法是否存在
onEvent专门触发事件
事件与委托的关系
事件真的是“以特殊方式声明的委托字段/实例”吗?
- 不是!只是声明的时候“看起来像”(对比委托字与事件的简化声明,field-like)
- 事件声明的时候使用了委托类型,简化声明造成事件看上去像一个委托的字段(实例),而event关键字则更像是一个修饰符–这就是错觉的来源之一
- 订阅事件的时候+=操作符后面可以是一个委托实例,这与委托实例的复制方法语法相同,这也让时间看起来像是一个委托字段–这是错觉的又一来源
- 重申:事件的本质是加装在委托字段上的一个“蒙版”(mask),是个起掩蔽作用的包装器。这个用于阻挡非法操作额“蒙版”绝不是委托字段本身
为什么要使用委托类型来声明事件
- 站在source的角度来看,是为了表明source能对外传递哪些消息
- 站在subscriber的角度来看,它是一种约定,是为了约束能够使用什么样的签名的方法来处理(响应)事件
- 委托类型的实例将用于存储(引用)事件处理器
对比事件与属性
- 属性不是字段–很多时候属性是字段的包装器,这个包装器用来保护字段不被滥用
- 时间不是委托字段—他是委托字段的包装器,这个包装器用来保护委托字段不被滥用
- 包装器永远都不可能是被包装的东西
- 作者:Kitety
- 链接:https://www.kitety.com/article/C-sharp-leraning-event-3
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章