首页 > 代码库 > 模拟C#的事件添加和删除

模拟C#的事件添加和删除

从《C# Via CLR》中的演化的一个小demo,探索事件的添加和删除原理,简单明了:

技术分享
  1 using System;  2 using System.Collections.Generic;  3 using System.Linq;  4 using System.Text;  5 using System.Threading;  6 using System.Threading.Tasks;  7   8 namespace ExpForEvent001  9 { 10     public sealed class EventKey : Object { } 11  12     public sealed class EventSet 13     { 14         private readonly Dictionary<EventKey, Delegate> m_events = new Dictionary<EventKey, Delegate>(); 15  16         public void Add(EventKey eventKey, Delegate handler) 17         { 18             Monitor.Enter(m_events); 19             Delegate d; 20             m_events.TryGetValue(eventKey, out d); 21             m_events[eventKey] = Delegate.Combine(d, handler);//Here we used Combine 22             Monitor.Exit(m_events); 23         } 24  25         public void Remove(EventKey eventKey, Delegate handler) 26         { 27             Monitor.Enter(m_events); 28             Delegate d; 29             if (m_events.TryGetValue(eventKey, out d)) 30             { 31                 d = Delegate.Remove(d, handler); 32  33                 if (d != null) m_events[eventKey] = d; 34                 else m_events.Remove(eventKey); 35             } 36             Monitor.Exit(m_events); 37         } 38  39         public void Raise(EventKey eventKey, Object sender, EventArgs e) 40         { 41             Delegate d; 42             Monitor.Enter(m_events); 43             m_events.TryGetValue(eventKey, out d); 44             Monitor.Exit(m_events); 45  46             if (d != null) 47             { 48                 d.DynamicInvoke(new Object[]{ sender, e }); 49             } 50         } 51     } 52  53     public class FooEventArgs : EventArgs { } 54  55     public class TypeWithLotsOfEvents 56     { 57         public readonly EventSet m_eventSet = new EventSet(); 58  59         protected EventSet EventSet { get { return m_eventSet; } } 60  61         #region Support Foo Event 62  63         protected static readonly EventKey s_fooEventKey = new EventKey(); 64  65         public event EventHandler<FooEventArgs> Foo 66         { 67             add { m_eventSet.Add(s_fooEventKey, value); } 68             remove { m_eventSet.Remove(s_fooEventKey, value); } 69         } 70  71         protected virtual void OnFoo(FooEventArgs e) 72         { 73             m_eventSet.Raise(s_fooEventKey, this, e); 74         } 75  76         public void SimulateFoo() { OnFoo(new FooEventArgs()); } 77  78         #endregion 79     } 80  81     class Program 82     { 83         static void Main(string[] args) 84         { 85             TypeWithLotsOfEvents twle = new TypeWithLotsOfEvents(); 86  87             twle.Foo += HandleFooEvent1; 88             twle.Foo += HandleFooEvent2; 89  90             twle.SimulateFoo(); 91         } 92  93         private static void HandleFooEvent1(object sender, FooEventArgs e) 94         { 95             Console.WriteLine("Handling Foo Event here..."); 96         } 97  98         private static void HandleFooEvent2(object sender, FooEventArgs e) 99         {100             Console.WriteLine("Handling Foo Event here2...");101         }102     }103 }
View Code

 

运行结果:

技术分享

 

附带Richter大神的一段话:

“JIT编译器能判断代码是否运行在一个Intel Pentium 4 CPU上,并生成相应的本地代码来利用Pentium 4支持的任何【特殊】指令,相反,非托管代码通常是针对通用的、具有最小功能集合的CPU编译的,不会使用提升应用程序性能的特殊指令。”

My words:

不同的体系结构的计算机其指令集是有差别的。软件越抽象则离硬件越远,从而阻挡了我们看到问题实质的视野。

模拟C#的事件添加和删除