CSharp Basic Tutorial Chapter-4-3 事件


Event 事件

  • 使用委托的时候,通常会出现两个角色,一个广播者,一个订阅者

广播和订阅

  • 使用委托的时候,通常会出现两个角色,一个广播者,一个订阅者
  • 广播者这个类型包含一个委托字段,广播者通过调用委托来决定什么时候进行广播。
  • 订阅者是方法目标的接收者,订阅者可以决定何时开始或结束监听,方式是通过在委托上调用+=和-=。
  • 一个订阅者不知道和不干扰其它的订阅者。

Event 事件

  • 事件就是将上述模式正式化的一个语言特性。

  • 事件是一种结构,为了实现广播者/订阅者模型,它只暴露了所需的委托特性的部分子集。

  • 事件的主要目的就是防止订阅者之间互相干扰。

    声明事件

  • 最简单的声明事件的方式就是在委托前面加上event关键字

内外区别对待

  • Broadercaster类型里面的代码拥有对PriceChanged的完全访问权,在这里就可以把它当作委托。
  • 而Broadercaster类型之外的代码只能对PriceChanged这个event执行+=或-=操作。

inout

事件在内部是如何工作的?
eventhow1

  • 首先,编译器把事件的声明翻译成类似下面的代码:

eventhow2

  • add 和 remove 关键字代表着显式的事件访问器,有点像属性访问器。
  • 然后编译器会查看Broadcaster内部对PriceChanged的引用,如果不是+=或-=的操作,那就直接把它们定向到底层的委托字段priceChanged。
  • 第三点,编译器把作用在event上的+=和-=操作翻译成调用add或remove访问器。

标准的事件模式

  • 为编写事件,.NET定义了一个标准的模式
  • System.EventArgs,一个预定义的框架类,除了静态的Empty属性之外,它没有其它成员。
  • EventArgs是为事件传递信息的类的基类。

例子
case

通常是根据所含有的信息进行命名,而不是所使用的事件
通常通过属性或只读字段来暴露数据

为事件选择或定义委托

  • 返回类型是void;
  • 接收两个参数,第一个参数类型是object,第二参数类型是EventArgs的子类。第一个参数表示事件的广播者,第二个参数包含需要传递的信息;
  • 名称必须以EventHandler结尾。

System.EventHandler

  • Framework定一了一个范型委托System.EventHandler,它满足上述规则。

eventhandler

针对选择的委托定义事件

defineevent

可触发事件的protected virtual方法

  • 方法名必须和事件一致,前面再加上On,接收一个EventArgs参数

protectvirtualdemo1
protectvirtualdemo2
protectvirtualdemo3
protectvirtualdemo4
protectvirtualdemo5

  • 多线程的场景下,你需要在测试或调用前,把委托赋给一个临时变量,来避免线程安全相关的错误:

error1

  • 在C#6之后,可以这样写:

error2

非范型的EventHandler

  • 当事件不携带多余信息的时候,可以使用非范型的EventHandler委托。
  • EventArgs.Empty属性

EventArgsEmpty

事件访问器

  • 事件访问器是事件的+=和-=函数的实现。
public event EventHandler PriceChanged;

编译器会把它转化为:

  • 一个私有的委托字段
  • 一对公共的事件访问器函数(add_PriceChanged和remove_PriceChanged),这两个函数的实现会把+=和-=操作交给私有的委托字段。
  • 也可以显式的定义事件访问器

显式定义的事件访问器

obviousDefine

  • 当事件访问器仅仅是另一个广播事件的类的中继。
  • 当类暴露大量event,但是大部分时候都只有少数的订阅者存在。
  • 显式实现一个声明了事件的接口。

事件修饰符

  • virtual,可以被重写;abstract,sealed,static。

classFoo


文章作者: Chaoqiang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Chaoqiang !
评论
 上一篇
CSharp Basic Tutorial hapter-4-4 Lambda 表达式 CSharp Basic Tutorial hapter-4-4 Lambda 表达式
什么是Lambda表达式Lambda表达式其实就是一个用来代替委托实例的未命名的方法;编译器会把Lambda表达式转化为以下二者之一: 一个委托实例 一个表达式树(expression tree),类型是Expression,它表示了可遍
下一篇 
CSharp Basic Tutorial Chapter-4-2 委托(下) CSharp Basic Tutorial Chapter-4-2 委托(下)
实例方法目标和静态方法目标 当一个实例方法被赋值给委托对象的时候,这个委托对象不仅要保留着对方法的引用,还要保留着方法所属实例的引用。 System.Delegate 的Target属性就代表着这个实例。 如果引用的是静态方法,那么Targ
  目录