为什么要在调用自定义事件之前检查 null ?

2023-11-26

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

Sample 1

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

Sample 2

DataChanged.Invoke(this);

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


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

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

采用这种形式有几个原因:

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

传递什么e有所不同,如果您需要通过EventArgs带有参数的descendant有两种方式:

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);

另请注意,在您的班级外部,该事件是一个事件,您只能add or remove来自它的事件处理程序。

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


另外,在 C# 6 中引入了一个新的运算符,?. - the 空条件运算符- 这基本上是缩写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你自己。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么要在调用自定义事件之前检查 null ? 的相关文章

  • C++:空类的对象的大小是多少?

    我想知道可能是什么空类对象的大小 肯定可以not为 0 字节 因为它应该可以像任何其他对象一样引用和指向它 但是 这样的物体有多大呢 我用了这个小程序 include
  • ~ C 中的运算符

    该程序的输出是 13 我从来没有完全理解 C 中的 运算符 为什么它给出 13 作为输出 如何将 运算符限制为数字的 4 位 include
  • 将 ManualResetEvent 包装为可等待任务

    我想等待手动重置事件 并超时并观察取消 我想出了类似下面的东西 手动重置事件对象由我无法控制的 API 提供 有没有办法在不占用和阻塞 ThreadPool 线程的情况下实现这一点 static Task
  • 在简单/未命名的 C# LINQ 组连接中排序内部密钥源

    我知道这个问题由于用词不同而读起来很奇怪 但这是使用的术语这个 MSDN 页面 http msdn microsoft com en us library bb311040 aspx从我正在学习 LINQ 组的地方开始 我将解释它们 我正在
  • 有关堆栈大小的警告消息

    I use Visual Studio 2010 with Code Analysis活性 在我的代码中 有一行在函数中分配一些内存 TCHAR someString 40000 代码分析抛出警告信息 警告 C6262 函数使用 40000
  • 如何获取picturebox非公开成员的值?

    我需要从 picturebox 的非公共成员获取图像矩形的值 如何获得该值 提前致谢 这是使用反射获取值的方法 PropertyInfo pInfo pictureBox1 GetType GetProperty ImageRectangl
  • ASP.NET身份更改密码

    我需要能够由管理员更改用户密码 因此 管理员不应输入用户的当前密码 他应该能够设置新密码 我查看了 ChangePasswordAsync 方法 但该方法需要输入旧密码 因此 此方法不适合此任务 因此我通过以下方式做到了 HttpPost
  • 如何更改 gdb 中的值

    所以我有这个家庭作业代码 我必须使用 gdb 进行调试 我发现了问题 但不知道如何使用gdb来改变它 define ARRAYSIZE 12 for i ARRAYSIZE 2 i gt 0 i for j i j lt ARRAYSIZE
  • 指示 GDB 6.5 使用目标文件中嵌入的源代码

    我一直在努力让GNU gdb 6 5 14在调试时使用嵌入在目标文件中的源代码 而不是扫描某些目录 主要原因是我是为嵌入式平台开发的 并且是交叉编译的 这意味着所有源代码都在我的电脑中 我读到了关于 ggdb3标志 其中包含许多额外信息 包
  • 如何在Linux上正确设置串行通信

    我正在尝试从 FPGA 板读取数据以及向 FPGA 板写入数据 该板本身附带一个驱动程序 每当板插入时 该驱动程序都会创建一个名为 ttyUSB0 的终端设备 在 FPGA 上 实现了异步接收器和发送器 并且它们似乎可以工作 然而 C 方面
  • 可变参数模板中的可变参数模板推导

    我不确定标题是否有意义 但这个例子实际上非常简单 A converter struct with a generic constructor template
  • 动态方法的实际例子?

    我想学习动态方法及其使用 C 的实际示例 动态方法和Reflection有什么关系吗 请帮我 我们正在使用动态方法来加速反射 这是我们的反射优化器的代码 只比直接调用慢10 比反射调用快2000倍 public class Reflecti
  • 如何在没有 ADO 包装器的情况下在 C# 中使用 SQLite

    这可能吗 我读过的所有文章都指出 ADO 包装器是必要的 但 SQLite 网站暗示除了 DLL 之外不需要其他任何东西 如果可能的话 我希望那里有代码示例 看这里 http www sqlite org cvstrac wiki p Sq
  • va_list 和 va_arg

    我这样使用 va list void foo const char firstArg va list args va start args firstArg for const char arg firstArg arg NULL arg
  • 实施黑名单的最有效方法

    我开发了一个 Ip 过滤器 并猜测我如何使用任何类型的 esque 数据结构开发一个非常高效且快速的黑名单过滤器 我想做的很简单 每个传入 传出连接我都必须检查被阻止的 IP 列表 IP是分散的 内存使用应该是线性的 不依赖于阻止列表的数量
  • 如何在 WinRT 中从 C++ 获取堆栈跟踪?

    我需要从 C 应用程序获取堆栈跟踪 并将其序列化为字符串 以便稍后解析 我在 Windows 上听说过的唯一 API 是 StackWalk64 它似乎不受支持 如何在 Windows 应用商店应用程序中从 C 获取堆栈跟踪 我能够调试复杂
  • 如何在Azure函数应用程序中调用函数后动态更改内容

    我正在使用 Visual Studio 2019 使用 Azure function v3 0 开发 Azure function 应用程序 我实现了一个时间触发的功能 我想更改内容 时间表 function json function j
  • 使用 解释 gprof 输出

    我试图在我的程序中找到性能问题 从而通过分析来检测代码 gprof 创建一个如下所示的平面配置文件 Flat profile Each sample counts as 0 01 seconds cumulative self self t
  • ListView 内的 TextBox 绑定到对象,双向绑定不起作用

    Edit 好吧 在尝试了无数次但没有成功之后 我创建了一个非常小的 Wpf 应用程序 您可以直接复制此代码 请注意 当您更改文本框中的值并按 测试 按钮时 这些值永远不会更新 我不明白为什么双向绑定不起作用 请帮忙 这是 xaml
  • HTTPS文件下载C#

    我需要下载隐藏在 HTTPS 连接后面的文件 我对下载安全网站后面的文件不熟悉 我尝试使用凭据来解决此问题 但无济于事 据我所知 您需要创建并使用证书来完成此操作 但我没有找到任何示例 任何帮助表示赞赏 这就是我现在所拥有的 WebClie

随机推荐

  • 同一数据上的多个轴

    我试图在相同的数据上使用两个轴 数据有几个DefaultTableXYDatasets 情节是一个XYPlot 我有两个XYLineAndShapeRenderers和一个StackedXYAreaRenderer2 y 值的所有数据均以米
  • 按(逆)时针顺序排列凹多边形顶点?

    我有一组无序的顶点 可能形成一个凹多边形 现在我想按顺时针或逆时针顺序排列它们 答案在这里建议采取以下步骤 找到多边形中心 计算角度 按角度对点排序 这显然仅适用于凸多边形 当点形成凹多边形时就会失败 我怎样才能对凹面做到这一点 我正在使用
  • 除非打印出来,否则值不会在 while 循环中更新[重复]

    这个问题在这里已经有答案了 好的 所以我有一个监视线程 它检查 ArrayList 的大小 并在该大小大于某个数字后执行某些操作 我现在遇到的问题是大小值永远不会更新 除非我的循环中有打印语句 这是一些代码来展示我到底要做什么 while
  • python中多条线的最近交点

    我需要一个好的算法来计算最接近 python 中的线集合的点 最好使用最小二乘法 我发现这篇关于 python 实现的文章不起作用 在Python中使用最小二乘法找到多条线的中心 我在 Matlab 中发现了这个资源 每个人似乎都喜欢 但我
  • 以编程方式在 Android 屏幕上移动鼠标指针

    我正在开发一个 Android 应用程序 我想在 Android 平板电脑上移动 鼠标 指针 光标 我知道这是可能的 因为当我将鼠标 USB 或 BT 连接到 Android 平板电脑 Honeycomb 时 会出现一个光标 并且我可以仅使
  • 如何在kotlin android中将base64字符串转换为图像

    我有一个表示位图图像的 Base64 字符串 我需要再次将该字符串转换为位图图像 以便在我的 Android 应用程序中的 ImageView 上使用它 怎么做 您可以使用此代码进行解码 val imageBytes Base64 deco
  • Ruby:Titleize:如何忽略较小的单词,如“and”、“the”、“or”等

    def titleize string string split map word word capitalize join end 这给每个单词起了标题 但是我如何捕获某些我不想大写的单词呢 即 杰克和吉尔 并且请不要使用正则表达式 UP
  • `const &&` 是否绑定到所有纯右值(和 xvalues)?

    C 标准定义了以下删除的函数 template
  • 使用 php 使用 WebService

    任何人都可以给我一个如何使用 php 使用以下 Web 服务的示例吗 http www webservicex net uszip asmx op GetInfoByZIP 这是一个使用curl 和GET 接口的简单示例 zip 97219
  • 正则表达式还是异常处理?

    以下哪一项是检查字符串是否浮动的更好做法 try Double parseDouble strVal catch NumberFormatException e My Logic or if strVal matches d d My Lo
  • 需要使用正则表达式对字符串执行通配符(*、?等)搜索

    我需要执行通配符 等 搜索字符串 这就是我所做的 string input Message string pattern d Regex regex new Regex pattern RegexOptions IgnoreCase if
  • 使用电话号码获取来电国家/地区名称? [复制]

    这个问题在这里已经有答案了 您好 有什么方法可以在 Android 手机上获取来电的国家 地区名称吗 Using 库电话号码 public String convertPhoneNumber String phoneNumber Phone
  • 使用 Zend_Db 时如何将值设置为 NULL

    当使用 Zend Db 执行 UPDATE 和 INSERT 查询时 我经常需要将值设置为 NULL 而不是 然而 Zend Db insert 和 Zend Db update 的默认行为似乎是将空值转换为空字符串 并按原样放入数据库中
  • 多次使用@Autowired

    我对春天很陌生 所以我可能会问一些愚蠢的问题 但无论如何 我已经构建了 Spring MVC 4 0 应用程序 我的设置是这样的 控制器 gt gt 服务 gt gt DAO 在控制器级别我使用大约 4 到 5 个不同的 Autowired
  • 如何将 create-react-app 部署到 Google Cloud

    我有一个前端 create react app 和一个使用 Expressjs 的后端 API 我成功地将后端 API 部署到 Google App Engine 但现在我需要将 create react app 部署到 Google Cl
  • Python单元测试模拟类和类方法

    我觉得这可能相对简单 但我正在费尽心思才能让它发挥作用 我想模拟整个类 然后指定该类的方法之一的返回值 我已经看过了here 在其他几个问题上 当然还有docs 我仍然无法让它发挥作用 请参阅下面我的简单示例 目录内容tmp tmp ini
  • 在 WCF 项目中设置 Web API

    我有一个有点 奇怪的做法 的问题 我们项目架构的要求是在 WCF 项目中设置具有 如果可能 所有 MVC 优点的 Web API 这意味着 WCF 和 Web API Web 服务将在一个项目中相互配合 这可行吗 我尝试了一下 发现即使合并
  • python + matplotlib:条形图显示不完整的 XTicklabels - 如何动态地将绘图区域移动到右侧以适合给定的 XTickLabels?

    我在用着matplotlib绘制一个barh绘制到文件 不幸的是 YTickLaels 有点太长 绘图区域不会自动向右移动 有没有办法自动将绘图区域移动到右侧 这样我就不会遇到不完整的 YTickLabels 问题 我使用的代码如下 imp
  • 设置 Google 地图信息窗口的样式

    我一直在尝试设计我的 Google 地图InfoWindow 但有关此主题的文档非常有限 你如何设计InfoWindow Google 编写了一些代码来协助完成此操作 这里有些例子 使用 InfoBubble 的示例 样式标记 and 信息
  • 为什么要在调用自定义事件之前检查 null ?

    这两个调用事件的代码示例有什么区别 Sample 1 public void OnDataChanged if DataChanged null DataChanged this Sample 2 DataChanged Invoke th