• C#之旅(三): 显式实现事件


    把《CLR VIA C#》又翻出来看了一下,看到11.4节的“显式实现事件”又有所领悟。当忙于项目进度的时候基本没什么时间可以静下心来翻阅下书籍,而只有经过项目的实战在回过头来去看些基础的知识,忽然会有种水到渠成的感觉。

    起初看到这个标题“显式实现事件”时我错误的当成了是显式实现接口了,看完之后才明白怎么回事,跟接口本就没半点的关系。原来显式实现事件就是为事件添加一个属性(add、remove)访问器。为什么要这么麻烦呢?在类里面添加事件不都这样的么:public event EventHandler myevent;有几个事件需要发布就写几行这样的代码,其它的工作编译器都会替我们解决了。但问题也就在于此,编译器会为event类型生成一个委托类型(这里是EventHandler)的实例字段,同时会生成两个方法:add_Xxx和remove_Xxx。假如事件数量很多,比如System.Windows.Forms.Control 类事件有70来个,要是以这种方式那么实例化一个Control对象就必须生成70多个委托类型的示例字段,这样的开销无疑是很大的。因此微软为了减少开销采取的方法就是“显式实现事件”。

    这里就有必要提下:EventHandlerList 提供一个简单的委托列表。从Control的基类Component可以看到它的定义 private EventHandlerList events;Control类会为每一个事件添加一个静态私有字段来作为Key->delegate映射保存到EventHandlerList 这个集合中来,作为Key的静态字段会在静态构造函数里进行实例化。调用事件的add访问器添加事件时先去events查找当前的Key值是否存在:存在就将事件添加到对应的委托链里面;不存在则添加Key->delegate的映射。

    作为Key的定义:

     1   private static readonly object EventAutoSizeChanged;
     2     private static readonly object EventBackColor;
     3     private static readonly object EventBackgroundImage;
     4     private static readonly object EventBackgroundImageLayout;
     5     private static readonly object EventBindingContext;
     6     private static readonly object EventCausesValidation;
     7     private static readonly object EventChangeUICues;
     8     private static readonly object EventClick;
     9     private static readonly object EventClientSize;
    10     private static readonly object EventContextMenu;
    11     private static readonly object EventContextMenuStrip;
    12     private static readonly object EventControlAdded;
    13     private static readonly object EventControlRemoved;
    14     private static readonly object EventCursor;
    15     private static readonly object EventDock;
    16     private static readonly object EventDoubleClick;
    17     private static readonly object EventDragDrop;
    ..........

    显式实现事件:

     1 public event EventHandler Click
     2 {
     3     add
     4     {
     5         base.Events.AddHandler(EventClick, value);
     6     }
     7     remove
     8     {
     9         base.Events.RemoveHandler(EventClick, value);
    10     }
    11 }
    12  
    13 ........
    14  

    EventHandlerList的定义:

      1 public sealed class EventHandlerList : IDisposable
      2 {
      3     // Fields
      4     private ListEntry head;
      5     private Component parent;
      6 
      7     // Methods
      8     public EventHandlerList()
      9     {
     10     }
     11 
     12     internal EventHandlerList(Component parent)
     13     {
     14         this.parent = parent;
     15     }
     16 
     17     public void AddHandler(object key, Delegate value)
     18     {
     19         ListEntry entry = this.Find(key);
     20         if (entry != null)
     21         {
     22             entry.handler = Delegate.Combine(entry.handler, value);
     23         }
     24         else
     25         {
     26             this.head = new ListEntry(key, value, this.head);
     27         }
     28     }
     29 
     30     public void AddHandlers(EventHandlerList listToAddFrom)
     31     {
     32         for (ListEntry entry = listToAddFrom.head; entry != null; entry = entry.next)
     33         {
     34             this.AddHandler(entry.key, entry.handler);
     35         }
     36     }
     37 
     38     public void Dispose()
     39     {
     40         this.head = null;
     41     }
     42 
     43     private ListEntry Find(object key)
     44     {
     45         ListEntry head = this.head;
     46         while (head != null)
     47         {
     48             if (head.key == key)
     49             {
     50                 return head;
     51             }
     52             head = head.next;
     53         }
     54         return head;
     55     }
     56 
     57     public void RemoveHandler(object key, Delegate value)
     58     {
     59         ListEntry entry = this.Find(key);
     60         if (entry != null)
     61         {
     62             entry.handler = Delegate.Remove(entry.handler, value);
     63         }
     64     }
     65 
     66     // Properties
     67     public Delegate this[object key]
     68     {
     69         get
     70         {
     71             ListEntry entry = null;
     72             if ((this.parent == null) || this.parent.CanRaiseEventsInternal)
     73             {
     74                 entry = this.Find(key);
     75             }
     76             if (entry != null)
     77             {
     78                 return entry.handler;
     79             }
     80             return null;
     81         }
     82         set
     83         {
     84             ListEntry entry = this.Find(key);
     85             if (entry != null)
     86             {
     87                 entry.handler = value;
     88             }
     89             else
     90             {
     91                 this.head = new ListEntry(key, value, this.head);
     92             }
     93         }
     94     }
     95 
     96     // Nested Types
     97     private sealed class ListEntry
     98     {
     99         // Fields
    100         internal Delegate handler;
    101         internal object key;
    102         internal EventHandlerList.ListEntry next;
    103 
    104         // Methods
    105         public ListEntry(object key, Delegate handler, EventHandlerList.ListEntry next)
    106         {
    107             this.next = next;
    108             this.key = key;
    109             this.handler = handler;
    110         }
    111     }
  • 相关阅读:
    数组按行访问和按列访问的区别
    解决github中图片无法显示问题的策略
    C#验证帮助类(手机号、身份证等)
    WPF圆角按钮样式
    弗洛伊德的本我、自我与超我概念
    KEPServerEX OPCUA服务器地址配置
    C#List的一些操作
    梦、清醒梦、梦魇
    类说明head部格式
    阅读笔记20222
  • 原文地址:https://www.cnblogs.com/yehuabin/p/2409041.html
Copyright © 2020-2023  润新知