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

时间:2010-04-08 07:16:29

标签: c# events event-handling

在MSDN上,我找到了以下内容:

public event EventHandler<MyEventArgs> SampleEvent;

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

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

也是如此
    if (temp != null)
        temp(this, new MyEventArgs(val));
}

2 个答案:

答案 0 :(得分:12)

这是一个与线程有关的偏执狂。如果另一个线程取消订阅之后的最后一个处理程序,您已经检查了null,那么可以成为 null你会引发异常由于委托是不可变的,因此将委托的快照捕获到变量中会阻止这种情况发生。

当然,它确实有其他副作用,你可以(而不是)最终针对一个认为已经取消订阅的对象引发事件......

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

答案 1 :(得分:2)

(从我在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#构造。保持等效event CIL代码中的关键字,所有语言和编辑都能够提供 特殊功能,因为他们可以将事件识别为特殊事件 班级成员。

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