具有空传播的事件引发的线程安全

Thread-safety of event raising with null propagation

这2个样品是一样的吗?老式的加注可以用Invoke和null propagation代替吗?

旧:

    public event EventHandler<MyEventArgs> MyEvent;
    protected virtual void OnMyEvent(MyEventArgs args)
    {
        EventHandler<MyEventArgs> handler = this.MyEvent;
        if (handler != null)
            handler(this, args);
    }

新:

    public event EventHandler<MyEventArgs> MyEvent;
    protected virtual void OnMyEvent(MyEventArgs args)
    {
        this.MyEvent?.Invoke(this, args);
    }

空值检查很重要,但很清楚。附加变量是什么?
零传播在内部是如何工作的?事件是线程安全的吗?

P.S。关于事件中的线程安全,您可以在这里阅读:
C# Events and Thread Safety

鉴于此代码:

    static void Main(string[] args)
    {
        var a = new Random(1).Next() > 0 ? new object() : null;
        var b = a?.GetHashCode();
        Console.WriteLine(b);
    }

这是我在发布模式 (VS 2015) 中调用 monadic 运算符的行的 IL 表示中看到的内容:

IL_0016: dup          
IL_0017: brtrue.s     IL_0025

... //nothing iteresting, just setting null to 'a' and skip IL_0025 area

IL_0025: callvirt     instance int32 [mscorlib]System.Object::GetHashCode()

让我解释一下:

  • dup - 是将堆栈上的当前值复制到此堆栈中的新值的命令(在这种情况下,它只是复制 'a' 的值)
  • brtrue.s - 如果堆栈上的值是 true/notnull/non-zero 则将控制转移到地址(截至目前值是 'a' 的副本 - 它是thread-safe使用它)

所以,你的问题的答案是:是的,thread-safe 使用 monadic 运算符,因为它是对副本进行操作。