在调用自定义事件之前,为什么要检查null? [英] Why should I check for null before I invoke the custom event?

查看:183
本文介绍了在调用自定义事件之前,为什么要检查null?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the difference between these two code samples for invoking an event?

示例1

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

样本2

DataChanged.Invoke(this);

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

When should I use each method to invoke a custom event? And why sometimes I get a NullReferenceException when I try to invoke event using DataChanged.Invoke(this), but when I convert the event invocation to the method in Sample 1 the DataChanged never becomes null anymore?

推荐答案

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

An OnXYZ method should always follow this form:

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

这有几个原因形式:


  1. 如果evt!= null 检查,确保我们不尝试调用一个 null 委托。如果没有人联系到事件处理程序,可能会发生这种情况。

  2. 在多线程方案中,由于代理是不可变的,一旦我们将代理的本地副本转换为code> evt ,我们可以在检查非空之后安全地调用它,因为没有人可以在之后修改它,如果但是在调用之前

  1. The if evt != null check ensures that we don't try to invoke a null delegate. This can happen if nobody has hooked up an event handler to the event.
  2. In a multithreaded scenario, since delegates are immutable, once we've obtained a local copy of the delegate into evt, we can safely invoke it after checking for non-null, since nobody can alter it after the if but before the call.

e 的通行不同,如果您需要传递 EventArgs 具有参数的后代有两种方式:

What to pass for e differs, if you need to pass an EventArgs descendant with a parameter there are two ways:

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

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

Also note that externally to your class, the event is an event, you can only add or remove event handlers from it.

事件是一个代表,你可以调用它,检查目标或方法,走出订阅者列表等。

Internal to your class, the event is a delegate, you can invoke it, check the target or method, walk the list of subscribers, etc.

另外,在C#6中有一个新的操作符,?。 - 无条件运算符 - 对于如果不是null,取消引用,这可以缩短此方法基本上是

Also, in C# 6 there is a new operator introduced, ?. - the Null-conditional operator - which is basically short for if not-null, dereference, which can shorten this method:

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成员进一步缩短: p>

which can be further shortened with the use of Expression-bodied members:

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

请注意,不可能这样写:

Please note that it is not possible to write this:

XYZ?.(sender, e);

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

so you must in this case use Invoke yourself.

这篇关于在调用自定义事件之前,为什么要检查null?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆