gpt4 book ai didi

c# - 为什么我应该在调用自定义事件之前检查是否为 null?

转载 作者:太空狗 更新时间:2023-10-29 22:07:10 25 4
gpt4 key购买 nike

这两个调用事件的代码示例有什么区别?

示例 1

public void OnDataChanged()
{
if (DataChanged != null)
{
DataChanged(this);
}
}

示例 2

DataChanged.Invoke(this);

我应该在什么时候使用每种方法来调用自定义事件?为什么有时我会在尝试使用 DataChanged.Invoke(this) 调用事件时得到 NullReferenceException,但当我将事件调用转换为示例 1 中的方法时,DataChanged永远不会变成 null 了吗?

最佳答案

OnXYZ 方法应始终遵循以下形式:

public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}

这种形式有几个原因:

  1. if evt != null 检查确保我们不会尝试调用 null 委托(delegate)。如果没有人将事件处理程序连接到事件,就会发生这种情况。
  2. 在多线程场景中,由于委托(delegate)是不可变的,一旦我们将委托(delegate)的本地副本获取到 evt 中,我们就可以在检查非空后安全地调用它,因为没有人可以更改它在 if 之后但在调用之前。

传递给 e 的内容不同,如果您需要传递带有参数的 EventArgs 后代,有两种方法:

public void OnXYZ(string p)
{
var evt = XYZ;
if (evt != null)
evt(sender, new SomeEventArgs(p));
}

或者更常见的是:

public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}

此语法:

evt(sender, e);

只是一种不同的写法:

evt.Invoke(sender, e);

另请注意,在您的类外部,事件是一个事件,您只能从中添加删除 事件处理程序。

在您的类内部,事件是一个委托(delegate),您可以调用它、检查目标或方法、遍历订阅者列表等。


此外,在 C# 6 中引入了一个新的运算符 ?。 - Null-conditional operator - 这基本上是 if not-null, dereference 的缩写,可以缩短此方法:

public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}

进入这个:

public void OnXYZ(SomeEventArgs e)
{
XYZ?.Invoke(sender, e);
}

可以使用 Expression-bodied 成员进一步缩短:

public void OnXYZ(SomeEventArgs e) => XYZ?.Invoke(sender, e);

请注意,这样写是不可能的:

XYZ?.(sender, e);

所以在这种情况下您必须自己使用Invoke

关于c# - 为什么我应该在调用自定义事件之前检查是否为 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33122371/

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