gpt4 book ai didi

c# - 检查事件是否为非空后事件为空

转载 作者:行者123 更新时间:2023-11-30 21:44:18 25 4
gpt4 key购买 nike

假设有如下代码片段(我使用的是.NET 4.0):

private void CauseTrouble()
{
if (MyEvent != null)
{
DoSomeIrrelevantCalculations();
MyEvent();
}
}

当运行包含此(简化)方法的相当大的程序时,在极少数情况下我会遇到来自 MyEvent() 的 NullReferenceException。调试器告诉我 MyEvent 为空,即使我刚刚检查它不为空。这是怎么回事?

现在有些人可能会立即说:“当然,如果你有一个多线程应用程序,另一个线程可能会在那些不相关的计算完成之前注销 myEvent 并且 - 砰! - 你有一个 NullReferenceException!”

这当然是真的,但在我深入多线程的黑暗之前(因为这是一个非常罕见的错误,我经常不得不等待几天才能再次发生),我需要知道是否还有其他可能性为了这件事发生?

具体来说:在非空检查成功后事件为空是否一定意味着另一个线程已取消注册该事件?

(我可以想象的另一种选择是外部非托管代码,它也由程序执行并且之前已经导致了一些数据访问冲突。是否有可能是那里的某些操作导致指向 MyEvent 的指针被覆盖?或者这应该是不可能的,因为代码片段是托管代码的一部分?我对这些东西太缺乏经验,无法分辨。)

如果你现在说:嘿,你为什么不记录所有注册/注销过程并自己检查发生了什么:你是对的。我已经在上面了。但正如我所说,如果运气不好,我可能需要一周的时间才能得到答复,同时我还想看看其他可能性。

更新

事情变得更奇怪了。假设是正确的,调试器显示 MyEvent 在被调用时确实为 null。所以我做了这里推荐的事情并替换了

if (MyEvent != null)
{
DoSomeIrrelevantCalculations();
MyEvent();
}

var handler = MyEvent;
if (handler != null)
{
DoSomeIrrelevantCalculations();
handler();
}

但这仍然会产生 NullReferenceException。调试显示调用 handler() 时 MyEvent 再次为空,但处理程序本身不是。如果对象甚至不为空,如何引发 NullReferenceException?

最佳答案

您有两个选择。如果您使用的是 C# 6.0 或更高版本,则可以使用 null 合并运算符。在幕后,它会阻止这个问题的发生。方法如下:

MyEvent?.Invoke();

如果您不使用 C# 6.0,则另一个选项很有用。只需先将其存储在变量中,检查变量,然后使用局部变量调用它,如下所示:

var eventHandler = MyEvent;
if (eventHandler != null)
{
eventHandler();
}

关于c# - 检查事件是否为非空后事件为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40938172/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com