我想澄清 BJ Myers 的(正确)答案。
在 C# 中,可以将事件视为委托类型的字段——就像可以将属性视为属性类型的字段一样——并且该“字段”的值可以为空。如果您不幸在一个线程上修改了事件处理程序,而另一个线程正在尝试调用它,您可能会遇到以下情况:
if (this.SomeEvent != null)
this.SomeEvent( ... );
不是线程安全的。该值可以被改变,使其在检查之前为非空,在检查之后为空,并且程序崩溃。
使这个“线程安全”的通常方法,我建议使用这个术语,是将值复制到本地,然后测试本地是否为空。这样做的好处是不会因空取消引用而崩溃。然而,聪明的开发者会注意到,还有一场比赛!序列可以是
- 缓存在线程 A 上的非空事件处理程序
- 线程 B 上的事件处理程序设置为 null
- 事件处理程序所需的状态在线程 B 上被销毁
- 事件处理程序在线程 A 上运行并可怕地死去
所以从这个意义上说,这种模式不是“线程安全的”。如果您处于这种不幸的境地,您有责任确保实施适当的线程逻辑,以免发生这种情况。你可以随心所欲地这样做。如果您想要能够在一个线程上调用事件处理程序同时在另一个线程上改变事件的(有问题的)好处,那么您必须支付使其安全或处理竞争条件错误的费用。
我个人会像瘟疫一样避免这种情况,但我不够聪明,无法编写正确的多线程代码。
现在,至于实际问题:
some_expression ?. ToString();
是相同的
temp = some_expression
temp == null ? null : temp.ToString()
您认为后一种代码是“线程安全的”吗?