An OnXYZ
方法应始终遵循以下形式:
public void OnXYZ()
{
var evt = XYZ;
if (evt != null)
evt(sender, e); // where to get e from differs
}
采用这种形式有几个原因:
- The
if evt != null
检查确保我们不会尝试调用null
代表。如果没有人将事件处理程序连接到该事件,则可能会发生这种情况。
- 在多线程场景中,由于委托是不可变的,一旦我们获得了委托的本地副本
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
你自己。