C# EventHandler文档代码示例

3
我正在阅读与EventHandlers相关的.NET文档,但不理解来自 https://learn.microsoft.com/en-us/dotnet/standard/events/ 的以下代码片段:
class Counter
{
    public event EventHandler ThresholdReached;

    protected virtual void OnThresholdReached(EventArgs e)
    {
        EventHandler handler = ThresholdReached;
        handler?.Invoke(this, e);
    }

    // provide remaining implementation for the class
}

本地变量handler的目的是什么?为什么不直接调用TresholdReached,如下所示:TresholdReached?.Invoke(this, e);? 类似的例子可以在这里找到:https://learn.microsoft.com/en-us/dotnet/api/system.eventhandler-1?view=net-5.0

2
在这种情况下,本地变量handler的目的是什么?它只是一个简短的示例,展示了event对象是强类型的。我认为编译器无论如何都会清除本地变量。 - Arthur Attout
2个回答

3
本地变量"handler"的目的是什么? 可能没有。从代码正确性的角度来看,确实没有理由。它似乎是旧版本文档的遗留物,在那个版本中,将事件字段“ThresholdReached”复制到本地变量中是必需的,以便安全地解决引发事件和任何其他可能取消订阅的代码之间的竞态条件。正如你指出的,使用空值运算符,该代码只需一行,通过事件字段本身调用即可。
我说“可能”是因为我猜作者使用更明确的代码形式希望达到某种其他教学目的。但我无法想象那可能是什么,而且显然干扰了对代码的普遍理解(即分散了注意力,从而忽略了重要部分)。
我在页面上提交了评论,让微软知道了这个问题。如果您愿意,我认为还可以在Microsoft Git repo中提交文档问题。
我的经验是,无论以哪种方式将问题传达给微软,他们通常会在相对短的时间内解决问题。我猜测,在接下来的几周内,该段落将得到修正,这个问题将不再相关。 :)

那么,使用空值条件运算符而不是!= null,就没有竞争危害了吗?(为什么?有相关文章吗?) - EpsilonDelta
正确。例如,请参见 https://dev59.com/g3A65IYBdhLWcg3wuRF8#32421459,https://dev59.com/EHVC5IYBdhLWcg3weBA-#32421409,https://dev59.com/NI_ea4cB1Zd3GeqPNmWH#32734529,https://dev59.com/w5Xfa4cB1Zd3GeqPjsFH#36425978 和 https://dev59.com/apffa4cB1Zd3GeqP5D1P#37338166。 - Peter Duniho
@CamiloTerevinto:不行,因为注释不能用于回答问题。甚至在提示中都明确说明了:“避免在评论中回答问题”。从技术角度来看,陈述多余代码是否真的是多余的并不是一种观点(请注意,我没有试图解决任何“非技术”方面的问题,这是正确的)。 - Peter Duniho

1

所以答案是:本地处理程序变量有效地复制了不可变委托并使其线程安全 - 这并不是真正的答案,因为即使没有局部变量副本,代码也已经是线程安全的。实际上,这似乎是你在第一次提出问题时的关键所在。我不明白过时的文档或博客文章如何解决与过时技术是否仍然相关的问题。 - Peter Duniho
复制事件处理程序实例本身就不是线程安全的。 - Blindy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接