以下两行代码几乎是等效的:
public event Action<EmployeeEventAgs> Leave;
相对于:
public event EventHandler<EmployeeEventAgs> Leave;
区别在于事件处理方法的签名。如果您使用带有操作的第一种方法,可以得到以下结果:
public void LeaveHandler(EmployeeEventAgs e) { ... }
然后是这个:
obj.Leave += LeaveHandler;
使用第二种方法时,LeaveHandler
的签名需要不同:
public void LeaveHandler(object sender, EmployeeEventAgs e) { ... }
很重要的是要注意,无论哪种情况下都使用了
event
关键字来声明事件成员。以这种方式声明的事件成员不仅仅是类的一个字段,尽管它看起来像是这样的。相反,编译器将其创建为一个
事件属性1。事件属性与普通属性类似,只是它们没有
get
或
set
访问器。编译器只允许它们在
+=
和
-=
赋值的左侧使用(添加或删除事件处理程序)。没有办法
覆盖已分配的事件处理程序,也没有办法
在声明该事件的类之外调用该事件。
如果两个示例中都缺少事件关键字,则可以执行以下操作而不会出错或警告:
obj.Leave = LeaveHandler;
这将清除所有已注册的处理程序并用LeaveHandler
替换它们。
此外,您还可以执行以下调用:
obj.Leave(new EmployeeEventAgs());
上述两种情况被认为是一种反模式,如果您想创建事件,则事件应仅由所有者对象调用,并且不应允许取消订阅者的无法跟踪的删除。
event
关键字是.NET的编程构造,可帮助您坚持正确使用事件。
考虑到上述内容,我认为许多人坚持使用
EventHandler
方法,因为很少会在没有
event
关键字的情况下使用
EventHandler
。 Action 的使用范围更广,但在用作事件时并不像事件那么自然。 后者当然是个人意见,因为事件处理程序方法可能已经在我的编码实践中变得太过硬化。 但是,如果正确使用操作,则使用它们来进行事件并不是违规的。
1 当编译器看到类似以下代码时,事件属性就是编译器自动生成的内容:
event EventHandler SomeEvent
它最终成为与以下代码大致相同:
private EventHandler _someEvent;
public event EventHandler SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
我们写成这样的事件调用:
this.SomeEvent(sender, args);
被转换为:
this._someEvent(sender, args)
Leave
处理程序声明为委托类型,而不是使用以下方式进行声明:public event EventHandler<> ...吗?使用event
关键字可以在处理公开事件的类时发挥巨大作用,因为如果没有该关键字,使用obj.Leave = someHandler
而不是obj.Leave += someHandler
可以轻松地清除整个事件集合。 - Ivaylo Slavov