有人可以在举办活动时向我解释以下声明的重要性。
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
由于我们只是将Threshold事件分配给处理程序,为什么我们不能简单地调用ThresholdReached(this,e)
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
}
public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
答案 0 :(得分:4)
拥有此第一行可防止多线程应用程序中的竞争条件。
想象一下,如果某个其他线程在您检查它是否为空之后取消订阅了事件。
检查null是必要的,因为没有任何处理程序的事件为null,并且您将通过调用此类事件获得NullReferenceException。
所以准确一点。
此代码不检查null并且可能抛出NullReferenceException:
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
ThresholdReached(this, e);
}
由于可能的竞争条件,这很危险,可能也会引发异常:
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
if (ThresholdReached != null)
ThresholdReached(this, e);
}
编辑(为了更好地解释局部变量的行为):
具有此分配会创建保持其状态的事件的本地副本。因此,如果任何线程取消订阅事件本地副本,则在方法调用的其余部分中保持相同。换句话说,委托的行为类似于复制结构而不是复制引用。
下面的代码会打印文字:
// let's assume ThresholdReached is null
ThresholdReached += MyHandler;
EventHandler<ThresholdReachedEventArgs> localCopy = ThresholdReached ;
ThresholdReached -= Program_SthEvent;
if (localCopy != null)
Console.WriteLine("we have a copy!");
注意localCopy
如何保持状态和值;