我见过开发人员使用以下代码。它们之间的确切区别是什么,哪些符合标准?它们是否相同,因为Action
和Func<T>
也是代理人:
public event Action<EmployeeEventAgs> OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
VS
public delegate void GoOnLeave(EmployeeEventAgs e);
public event GoOnLeave OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
答案 0 :(得分:50)
Fwiw,这两个例子都没有使用标准的.NET约定。 EventHandler<T>
泛型应该声明事件:
public event EventHandler<EmployeeEventArgs> Leave;
“On”前缀应保留用于引发事件的受保护方法:
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null) handler(this, e);
}
你没有有这样做,但任何人都会立即识别模式,理解你的代码并知道如何使用和定制它。
它的最大优点是不必在自定义委托声明和Action<>
之间进行选择,EventHandler<>
是最好的方法。哪个回答你的问题。
答案 1 :(得分:27)
以下两行代码几乎相同:
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
个访问者。编译器允许它们仅在+=
和-=
赋值的左侧使用(添加或删除事件处理程序)。无法覆盖已分配的事件处理程序,或调用声明的类之外的事件。
如果两个示例中都缺少event关键字,则可以执行以下操作,不会出现错误或警告:
obj.Leave = LeaveHandler;
将删除所有已注册的处理程序并将其替换为LeaveHandler
。
此外,您还可以执行此调用:
obj.Leave(new EmployeeEventAgs());
如果您打算创建事件,则上述两种情况被视为反模式。应仅由所有者对象调用事件,并且不应允许无法删除删除订阅者。 event
关键字是.NET的程序化结构,可帮助您坚持正确使用事件。
考虑到上述情况,我相信很多人会坚持使用EventHandler
方法,因为如果不使用EventHandler
关键字,则更不可能使用event
。操作具有更广泛的使用范围,当用作事件时它们看起来不那么自然。当然,后者是个人意见,因为事件处理程序方法在我自己的编码实践中可能变得太硬了。但是,如果行动得当,将其用于事件并非犯罪行为。
1 事件属性是编译器在看到如下代码时自动生成的:
event EventHandler SomeEvent
它与以下代码大致相同:
private EventHandler _someEvent; // notice the lack of the event keyword!
public event EventHandler SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
我们写的事件调用:
this.SomeEvent(sender, args);
转换为:
this._someEvent(sender, args);
答案 2 :(得分:21)
Action<T>
与delegate void ... (T t)
Func<T>
与delegate T ... ()
答案 3 :(得分:6)
行动只是完整委托声明的捷径。
public delegate void Action<T>(T obj)
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
使用哪一个取决于您的组织编码标准/风格。
答案 4 :(得分:4)
是的,Action和Func只是在3.5 clr。
中定义的便利代表Action,Func和lambdas都只是语法糖和使用委托的便利。
他们没有什么魔力。有些人编写了简单的2.0插件库来将此功能添加到2.0代码中。
答案 5 :(得分:4)
You may want to look here ,看看编译器为Action实际生成的内容是最佳描述。你所写的内容没有功能上的区别,只是更短,更方便的语法。
答案 6 :(得分:3)
一般来说,它们是等价的。但是在使用委托作为事件类型的上下文中,约定是使用EventHandler(其中T继承EventArgs):
public event EventHandler<EmployeeEventArgs> Left;
public void Leave()
{
OnLeft(this.ID);
}
protected virtual void OnLeft(int id)
{
if (Left != null) {
Left(new EmployeeEventArgs(id));
}
}
答案 7 :(得分:0)
你可以自己编写这些Action和Func泛型代理,但由于它们通常很有用,所以它们会为你编写它们并将它们放在.Net库中。