具有空传播的事件引发的线程安全
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 运算符,因为它是对副本进行操作。
这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 运算符,因为它是对副本进行操作。