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     }
原文地址:https://www.cnblogs.com/yehuabin/p/2409041.html