模拟C#的事件添加和删除
从《C# Via CLR》中的演化的一个小demo,探索事件的添加和删除原理,简单明了:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
运行结果:
附带Richter大神的一段话:
“JIT编译器能判断代码是否运行在一个Intel Pentium 4 CPU上,并生成相应的本地代码来利用Pentium 4支持的任何【特殊】指令,相反,非托管代码通常是针对通用的、具有最小功能集合的CPU编译的,不会使用提升应用程序性能的特殊指令。”
My words:
不同的体系结构的计算机其指令集是有差别的。软件越抽象则离硬件越远,从而阻挡了我们看到问题实质的视野。