23.12.15 《CLR via C#》 笔记8

第十一章 事件

  1. 事件是在类中定义的一种成员,定义了事件成员的类型可以:

    1. 方法能登记对事件的关注
    2. 方法能注销对事件的关注
    3. 事件发生时,登记了的方法会收到通知
  2. 设计要公开事件的类型

    1. 定义类型(容纳要发给事件接收者的附加信息)

      该类型应该从System.EventArgs派生,而且类名以EventArgs结尾

      定义不要附加数据的事件时,可直接使用EventArgs.Empty

    2. 定义事件成员

      以event关键字定义,需要指定访问性(一般一定是public),委托类型和名称

      例:public event EventHandler<XXXEventArgs> eventName

      对应方法原型必须为:

      void MethodName(Object sender, XXXEventArgs e);

      (事件模式要求sender为Object类型,参数名为e,返回类型为void)

    3. 定义引发事件的方法

      定义一个受保护的虚方法,参数为XXXEventArgs

      要引发事件时,类及派生类的代码调用该方法(如果有对象登记了对事件的关注,那么通知那些对象)

      为了线程安全,一般先将委托字段复制到临时变量中,用临时变量引用赋值发生时的委托链

      例:var temp = Volatile.Read(ref eventName)

    4. 定义方法将输入转化为事件

      即在合适时机,调用虚方法通知关注了事件的对象

  3. 编译器如何实现事件

    在定义了事件成员后,C#编译器将会构造:

    1. 一个被初始化为null的委托字段,始终是private(即使事件被定义为public)
    2. 一个add_XXX方法,和事件的访问性一致,调用System.Delegate.Combine方法
    3. 一个remove_XXX方法,和事件的访问性一致,调用System.Delegate.Remove方法
  4. 设计侦听事件的类型

    使用+=操作符登记对象对事件的关注(内部被翻译成add_XXX方法)

    使用-=操作符注销对象对事件的关注(内部被翻译成remove_XXX方法)

  5. 显式实现事件

    1. 问题:如果一个类提供大量事件,那么这个类的每个对象都要准备大量字段(编译器为事件成员构造私有的委托字段),由于有些事件不常用,造成内存浪费
    2. 解决:显式实现事件,而不是让编译器自己完成构造
    3. 步骤
      1. 额外定义一个类,用于储存事件(类中包含一个集合,通常使用字典(key是事件类型,value是委托列表))
      2. 在该类中实现Add(key, value),Remove(key,value),Raise(key,sender,e)方法
      3. 在类的本体中,定义:
        1. 刚才额外定义的集合类字段,用于储存事件
        2. 为每种事件定义:
          1. 一个静态只读对象(拥有独立的哈希码,作为key)
          2. 事件访问器方法(显式实现add和remove(调用集合类的Add,Remove方法))
          3. 定义引发事件的,受保护的虚方法(调用集合类的Raise方法)
          4. 定义将输入转化为事件的方法(调用引发事件的方法)

相关推荐

  1. 231211 刷题日报

    2023-12-16 07:40:02       66 阅读
  2. CentOS 8使用笔记

    2023-12-16 07:40:02       40 阅读
  3. c++学习笔记8

    2023-12-16 07:40:02       30 阅读
  4. 代数学笔记8: Sylow定理

    2023-12-16 07:40:02       46 阅读
  5. css学习笔记8(定位)

    2023-12-16 07:40:02       49 阅读
  6. k8s学习笔记

    2023-12-16 07:40:02       39 阅读
  7. rust学习笔记8-12)

    2023-12-16 07:40:02       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-16 07:40:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-16 07:40:02       101 阅读
  3. 在Django里面运行非项目文件

    2023-12-16 07:40:02       82 阅读
  4. Python语言-面向对象

    2023-12-16 07:40:02       91 阅读

热门阅读

  1. python在车载电子测试方面的应用笔记【1】

    2023-12-16 07:40:02       66 阅读
  2. springboot rabbitmq 发布订阅 广播模式

    2023-12-16 07:40:02       71 阅读
  3. k8s1.24+prometheus+grafana容器监控与告警

    2023-12-16 07:40:02       36 阅读
  4. 2-go-变量定义、类型、常量、函数

    2023-12-16 07:40:02       56 阅读
  5. flutter学习-day11-容器类组件

    2023-12-16 07:40:02       56 阅读
  6. 【Hadoop】WordCount源码分析

    2023-12-16 07:40:02       67 阅读
  7. Spring Boot中实现邮件推送

    2023-12-16 07:40:02       55 阅读
  8. 飞天使-实际运用安装rabbitmq

    2023-12-16 07:40:02       61 阅读
  9. 单片机Freertos入门(二)任务调度的介绍

    2023-12-16 07:40:02       45 阅读