简而言之,我想知道C#的null传播会安全地允许我在发出一个本来需要局部变量的事件时避免竞争条件。
为了说明,请考虑以下暴露事件的类(“FooEvent”和3种不同的信号传递方式。
using System;
public class FooArgs
{
}
public class Foo
{
public event EventHandler<FooArgs> FooEvent;
public Foo()
{
}
public void SignalEvent()
{
// UNSAFE: Race condition between checking null
// and invoking event could lead to crash if client
// unsubscribes in the interim.
if (FooEvent != null)
FooEvent(this, new FooArgs());
}
public void SignalEvent2()
{
// SAFE: Get event subscribers into a local and THEN
// invoke to avoid race condition.
var f = FooEvent;
if (f != null)
f(this, new FooArgs());
}
public void SignalEvent3()
{
// NULL PROPAGATION: Is this safe or not? Is the null
// checked before invoking each client or only once?
FooEvent?.Invoke(this, new FooArgs());
}
}
第一种方法是不安全的,因为客户端可以在检查null之后但在调用处理程序之前取消订阅。
第二种方法是安全的,因为您首先获得订阅者的本地副本。
第三种方法最冗长,最具吸引力。这也是我多次见过的建议。但它的安全性都取决于何时真正检查零传播。如果订阅了2个客户端,并且在第一个和第二个调用Notify()的时间和第二个取消订阅之间,该怎么办?是否在每个客户端之前检查空传播或仅检查一次?