在调用自定义事件之前,为什么要检查null? [英] Why should I check for null before I invoke the custom event?
问题描述
这两个调用事件的代码示例有什么区别?
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
}
这有几个原因形式:
- 如果evt!= null 检查,
确保我们不尝试调用一个
null
委托。如果没有人联系到事件处理程序,可能会发生这种情况。 - 在多线程方案中,由于代理是不可变的,一旦我们将代理的本地副本转换为code> evt ,我们可以在检查非空之后安全地调用它,因为没有人可以在
之后修改它,如果
但是在调用之前
- The
if evt != null
check ensures that we don't try to invoke anull
delegate. This can happen if nobody has hooked up an event handler to the event. - 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 theif
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屋!