在真实的项目中,有的对象有相当多的事件,例如一个窗体就有好多种事件。默认情况下,当声明事件时,编译器将内存分配给一个事件字段,一存储事件信息。如果类中有好多事件未使用,则他们会不必要的占用内存。

这种情况下,.NETFramework提供了EventHandlerList类来减少内存的占用。它可以被看作事件的集合,只有需要响应的事件才拥有方法调用列表,才会在EventHandlerList对象中出现。

EventHandlerList:

为了节省内存而设计的。
当你定义一个事件的时候,通常也要定义相应的委托,在初始化的时候,就会为所有事件、委托分配内存空间。
但如果有许多未被使用到的事件,那么这些空间就浪费了。
EventHandlerList是专门用于保存委托的线性表,它存储的是Delegate类型,所有委托的基类,也就是任意委托都可存储。
可以看到无论是Form,还是HttpAppliaction类,都有定义一个EventHandlerList类型的Events属性,用于存储所有事件委托

如果用EventHandlerList对象来保存事件的相应方法,必须为每一个事件编写特殊的访问器:

class MyControl1
{
    // 即使没有订阅,每个事件作为类成员需要4个字节(的引用,没有订阅时为null)。
    // Winform的控件至少有70个事件, 这就要280个字节,且大部分事件都没有被用到。
    // 就是说每个UI上的控件,Lable,Button,TextBox,等等,每个都可能浪费约300个字节。
    public event EventHandler Initializing;
    public event EventHandler Initialized;
    // ...
    public event EventHandler MouseDown;
    public event EventHandler MouseUp;
    public event EventHandler MouseMove;
    public event EventHandler MouseClick;
    public event EventHandler MouseDoubleClick;
    public event EventHandler KeyDown;
    public event EventHandler KeyUp;
    // ...
}
 
class MyControl2
{
    // 一个EventHandlerList初始只要4个字节(的引用)
    private EventHandlerList _events;
    protected EventHandlerList Events
    {
        get 
        
            if (_events == null) _events = new EventHandlerList();
            return _events;
        }
    }
 
    public event EventHandler Initializing
    {
        add { Events.AddHandler("Initializing", value); }  // 按需增加
        remove { Events.RemoveHandler("Initializing", value); }
    }
 
    public event EventHandler Initialized
    {
        add { Events.AddHandler("Initialized", value); }
        remove { Events.RemoveHandler("Initialized", value); }
    }
}
说明:只有在事件很多的情况下需要,本身事件不多的控件,没有必要设置事件访问器
 
 
一般的事件也可以写事件访问器,如果不写,也不会有什么影响,因为.net会自动生成,对于lock,在4.0以后没有什么意义,.net已经优化了访问过程。
特此在这说明是为了我们看一些老的代码的时候,能够理解是在做什么。
    public class Shape : IDrawingObject, IShape  

{  // Create an event for each interface event

    event EventHandler PreDrawEvent;

    event EventHandler PostDrawEvent;

    object objectLock = new Object();

    event EventHandler IDrawingObject.OnDraw

{

add

{  lock (objectLock)

{

PreDrawEvent += value;

}

}

remove

{

    lock (objectLock)

{

PreDrawEvent -= value;

}

}

}

C#事件の事件访问器的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

  2. JavaScript DOM高级程序设计 4.3控制事件流和注册事件侦听器--我要坚持到底!

    一.事件流 我们通过下面一个实例,进行说明. <body> <h1>Event Flow</h1> <ul id="nav"> &l ...

  3. js事件流、事件处理程序/事件侦听器

    1.事件流 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档). 事件捕获 ...

  4. javascript中事件总结&通用的事件侦听器函数封装&事件委托

    前言: JAVASCRIPT与HTML之间的交互是通过事件来实现的.事件,就是文档或浏览器窗口中发生的一些特定交互瞬间.可以使用侦听器( 或处理程序 )来预定事件,以便事件发生时执行相应的代码.这种在 ...

  5. 052_末晨曦Vue技术_处理边界情况之程序化的事件侦听器

    程序化的事件侦听器 点击打开视频讲解更详细 现在,你已经知道了 $emit 的用法,它可以被 v-on 侦听,但是 Vue 实例同时在其事件接口中提供了其它的方法.我们可以: 通过 $on(event ...

  6. Android事件侦听器回调方法浅谈

    http://developer.51cto.com/art/201001/180846.htm Android事件侦听器作为视图View类的接口,其中包含有不少回调方法,比如:onClick():o ...

  7. Yarn源码分析之事件异步分发器AsyncDispatcher

    AsyncDispatcher是Yarn中事件异步分发器,它是ResourceManager中的一个基于阻塞队列的分发或者调度事件的组件,其在一个特定的单线程中分派事件,交给AsyncDispatch ...

  8. C#属性访问器

    属性的访问器包含与获取或设置属性有关的可执行语句.访问器声明可以包含 get 访问器或 set 访问器,或者两者均包含.声明采用下列形式之一:get {}set {} get 访问器get 访问器体与 ...

  9. 【温故而知新-万花筒】C# 异步编程 逆变 协变 委托 事件 事件参数 迭代 线程、多线程、线程池、后台线程

    额基本脱离了2.0 3.5的时代了.在.net 4.0+ 时代.一切都是辣么简单! 参考文档: http://www.cnblogs.com/linzheng/archive/2012/04/11/2 ...

随机推荐

  1. mysql+高可用MMM

    一. MMM 简介:MMM 即 Multi-Master Replication Manager for MySQL:mysql 多主复制管理器,基于 perl 实现,关于 mysql 主主复制配置的 ...

  2. wpf学习20180606

    对象元素的子元素 有三类子元素:内容属性.集合项.值(类型转换) ------------------------------------------------------------------- ...

  3. npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\package.json'

    在使用 npm 命令安装常用的 Node.js web框架模块 express时出现: 解决方法是 在命令行切换到安装nodejs文件下的nodejs\node_modules\npm  后执行npm ...

  4. Java 内部类及其原理

    Java中实现内部类 内部类相信大家都用过很多次了,就不说它是怎么用的了. 内部类 1.成员内部类 需要注意的是, 当成员内部类拥有和外部类同名的成员变量或这方法时, 默认情况下访问的是内部类的成员, ...

  5. 汇编语言--微机CPU的指令系统(五)(移位操作指令)

    (5) 移位操作指令 移位操作指令是一组经常使用的指令,它包括算术移位.逻辑移位.双精度移位.循环移位和带进位的循环移位等五大类. 移位指令都有指定移动二进制位数的操作数,该操作数可以是立即数或CL的 ...

  6. 清除float影响

    条件: 父元素中有子元素float的话,可能就会影响父元素的高度,从而影响布局: 解决方案: 1.直接给父元素定高: 弊端:必须知道父元素的高: 2. 父元素使用overflow属性值为hidden解 ...

  7. 微信小程序之发送模板消息(通过openid推送消息给用户)

    一.获取access_token access_token是接口调用的凭证,目前有效期为两个小时,需要定时刷新,重复获取将导致上次获取的access_token失效.(注:不建议每次调用需要acces ...

  8. vuejs-指令详解

    v-if v-if指令可以完全根据表达式的值在DOM中生成或移除一个元素.如果v-if表达式赋值为false,那么对应的元素就会从DOM中移除:否则,对应元素的一个克隆将被重新插入DOM中,代码如下: ...

  9. 洛谷P4577 [FJOI2018]领导集团问题(dp 线段树合并)

    题意 题目链接 Sol 首先不难想到一个dp,设\(f[i][j]\)表示\(i\)的子树内选择的最小值至少为\(j\)的最大个数 转移的时候维护一个后缀\(mx\)然后直接加 因为后缀max是单调不 ...

  10. 通俗的理解java设计模式的准则

    本文部分内容摘抄自https://www.cnblogs.com/dolphin0520/p/3919839.html,加入了自己的理解: 一.单一职责原则 原文链接:http://blog.csdn ...