这两个代码示例之间用于调用事件的区别是什么?
样品1
public void OnDataChanged()
{
if (DataChanged != null)
{
DataChanged(this);
}
}
Run Code Online (Sandbox Code Playgroud)
样本2
DataChanged.Invoke(this);
Run Code Online (Sandbox Code Playgroud)
我应该何时使用每种方法来调用自定义事件?为什么有时我尝试使用调用事件时会得到NullReferenceException DataChanged.Invoke(this),但是当我将事件调用转换为示例1中的方法时,DataChanged永远不会变为null?
ang*_*son 15
一种OnXYZ方法应该始终遵循这种形式:
public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}
Run Code Online (Sandbox Code Playgroud)
这种形式有几个原因:
if evt != null检查是为了确保我们不要试图调用null委托.如果没有人将事件处理程序连接到事件,就会发生这种情况.evt,我们可以在检查非null之后安全地调用它,因为没有人可以if在调用之后但在调用之前更改它.要传递的内容e有所不同,如果需要传递EventArgs带有参数的后代,有两种方法:
public void OnXYZ(string p)
{
var evt = XYZ;
if (evt != null)
evt(sender, new SomeEventArgs(p));
}
Run Code Online (Sandbox Code Playgroud)
或者更常见的是:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
Run Code Online (Sandbox Code Playgroud)
这个语法:
evt(sender, e);
Run Code Online (Sandbox Code Playgroud)
只是一种不同的写作方式:
evt.Invoke(sender, e);
Run Code Online (Sandbox Code Playgroud)
另请注意,在您的类外部,事件是一个事件,您只能add或remove事件处理程序来自它.
在您的类的内部,事件是委托,您可以调用它,检查目标或方法,遍历订阅者列表等.
此外,在C#6中引入了一个新的运算符,?.- Null条件运算符 - 它基本上是简称if not-null, dereference,可以缩短此方法:
public void OnXYZ(SomeEventArgs e)
{
var evt = XYZ;
if (evt != null)
evt(sender, e);
}
Run Code Online (Sandbox Code Playgroud)
进入这个:
public void OnXYZ(SomeEventArgs e)
{
XYZ?.Invoke(sender, e);
}
Run Code Online (Sandbox Code Playgroud)
可以通过使用表达身体成员进一步缩短:
public void OnXYZ(SomeEventArgs e) => XYZ?.Invoke(sender, e);
Run Code Online (Sandbox Code Playgroud)
请注意,不能写这个:
XYZ?.(sender, e);
Run Code Online (Sandbox Code Playgroud)
所以你必须在这种情况下使用Invoke自己.
| 归档时间: |
|
| 查看次数: |
1575 次 |
| 最近记录: |