关于事件的价值/参考类型的问题

在MSDN上,我发现以下内容:

public event EventHandler SampleEvent; public void DemoEvent(string val) { // Copy to a temporary variable to be thread-safe. EventHandler temp = SampleEvent; 

是参考吗?
如果是这样,我不理解其含义,因为当SampleEvent变为null时,temp也是如此

  if (temp != null) temp(this, new MyEventArgs(val)); } 

这是与线程有关的偏执狂。 如果另一个线程您将其检查为null 之后取消订阅最后一个处理程序,则它可能变为 null并且您将导致exception。 由于委托是不可变的,因此将委托的快照捕获到变量中会阻止这种情况发生。

当然,它确实有另一个副作用,你可以(而不是)最终提高事件对一个认为已经取消订阅的对象…

但要强调 – 当多个线程订阅/取消订阅对象时,这只是一个问题,这是:罕见,而b:不完全合乎需要。

(从我在Essential C#4.0中读到的内容)

基本上,从这个C#代码:

 public class CustomEventArgs: EventArgs {…} public delegate void CustomEventHandler(object sender, CustomEventArgs a); public event CustomEventHandler RaiseCustomEvent; 

编译器将生成等效于以下C#代码的CIL代码(松散):

 public delegate void CustomEventHandler(object sender, CustomEventArgs a); private CustomEventHandler customEventHandler; // <-- generated by the compiler public void add_CustomEventHandler(CustomEventHandler handler) { System.Delegate.Combine(customEventHandler, handler); } public void remove_CustomEventHandler(CustomEventHandler handler) { System.Delegate.Remove(customEventHandler, handler); } public event CustomEventHandler customEventHandler { add { add_customEventHandler(value) } remove { remove_customEventHandler(value) } } 

复制事件时,实际上是复制private CustomEventHandler customEventHandler 。 由于委托是不可变的,因此在修改原始customEventHandler时不会影响副本。 您可以尝试使用此代码来查看我的意思:

 string s1 = "old"; string s2 = s1; s1 = "new"; // s2 is still "old" 

关于生成的CIL代码需要注意的另一个重要特性是event关键字的CIL等价物保留在CIL中。 换句话说,事件是CIL代码明确识别的事物; 它不仅仅是一个C#构造。 通过在CIL代码中保留等效event关键字,所有语言和编辑者都能够提供特殊function,因为他们可以将事件识别为特殊的类成员。

我猜你很困惑,主要是因为你认为事件是一个类的糖语法,对吧?