触发事件的潜在缺点?

abe*_*nky 11 c# events race-condition

Microsoft的事件教程显示了如何在触发之前检查eventfor null:

protected virtual void OnChanged(EventArgs e) 
{
    if (Changed != null)
    {   // Potential Race-condition at this point!
        Changed(this, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

但这会留下一个竞争条件,正如Eric Lippert的博客中所详述的那样,他写道应该通过本地事件触发事件以避免竞争条件:

protected virtual void OnChanged(EventArgs e) 
{
    ChangedEventHandler temp = Changed;  // Local copy of the EventHandler
    if (temp != null)
    {                                    // Race condition avoided by local variable.
        temp(this, e);
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然这很有效,但它让许多错误的开发人员感到困惑,并且不会把它放在本地范围的事件中.


来自DailyCoding的另一个解决方案是始终将事件初始化为具有一个空处理程序,因此永远不需要进行空检查:

// Set with empty delegate, will never be null
public event ChangedEventHandler Changed = delegate { };

protected virtual void OnChanged(EventArgs e) 
{
    // Neither Null-check nor local variable is needed; just trigger the event.
    Changed(this, e);
}
Run Code Online (Sandbox Code Playgroud)

这个很有意义,而且非常简单.
但是,由于我看到这种技术很少在网上提及,我认为必须有一个原因.
使用像这样的空委托初始化事件是否有缺点?

And*_*own 1

您将看到绝对微小的性能影响,但在更高级的情况下会出现问题,例如序列化和反序列化类可能会导致您丢失假事件处理程序,并且缺少空检查然后引发异常。