C# Action<T> 与委托事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2282476/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Action<T> vs delegate event
提问by Bhaskar
I have seen developers using the below codes quite alternatively. What is the exact difference between these, and which ones go by the standard? Are they same, as Action
and Func<T>
is a delegate as well:
我已经看到开发人员交替使用以下代码。这些之间的确切区别是什么,哪些符合标准?它们是否相同,Action
并且Func<T>
也是代表:
public event Action<EmployeeEventAgs> OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
VS
VS
public delegate void GoOnLeave(EmployeeEventAgs e);
public event GoOnLeave OnLeave;
public void Leave()
{
OnLeave(new EmployeeEventAgs(this.ID));
}
采纳答案by Hans Passant
Fwiw, neither example uses standard .NET conventions. The EventHandler<T>
generic should declare the event:
Fwiw,这两个示例都没有使用标准的 .NET 约定。在EventHandler<T>
一般的应申报的事件:
public event EventHandler<EmployeeEventArgs> Leave;
The "On" prefix should be reserved for a protected method that raises the event:
“On”前缀应保留用于引发事件的受保护方法:
protected virtual void OnLeave(EmployeeEventArgs e) {
var handler = Leave;
if (handler != null) handler(this, e);
}
You don't haveto do it this way, but anybody will instantly recognize the pattern, understand your code and know how to use and customize it.
你不具备做这种方式,但任何人一眼就能认出的模式,理解你的代码,并知道如何使用和定制。
And it has the great advantage of not being forced to choose between a custom delegate declaration and Action<>
, EventHandler<>
is the best way. Which answers your question.
并且它的巨大优势是不必在自定义委托声明和Action<>
,之间进行选择,这EventHandler<>
是最好的方法。这回答了你的问题。
回答by Sky Sanders
Yes, Action and Func are simply convenience delegates that have been defined in the 3.5 clr.
是的,Action 和 Func 只是在 3.5 clr 中定义的便利委托。
Action, Func and lambdas are all just syntactical sugar and convenience for using delegates.
Action、Func 和 lambdas 都只是语法糖和使用委托的便利。
There is nothing magic about them. Several people have written simple 2.0 addon libraries to add this functionality to 2.0 code.
他们没有什么神奇之处。有几个人编写了简单的 2.0 插件库来将此功能添加到 2.0 代码中。
回答by pdr
Action<T>
is exactly the same as delegate void ... (T t)
Action<T>
完全一样 delegate void ... (T t)
Func<T>
is exactly the same as delegate T ... ()
Func<T>
完全一样 delegate T ... ()
回答by Nick Craver
You may want to look here, seeing what the compiler actually generates for Action is the best description. There's no functional difference in what you wrote, just shorter, more convenient syntax.
你可能想看这里,看看编译器实际为 Action 生成的内容是最好的描述。您编写的内容没有功能差异,只是语法更短、更方便。
回答by Darryl Braaten
Action is just a shortcut for the full delegate declaration.
Action 只是完整委托声明的快捷方式。
public delegate void Action<T>(T obj)
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
Which one to use would depend on your organizations coding standards/style.
使用哪一种取决于您的组织编码标准/风格。
回答by Rafa Castaneda
In general, they are equivalent. But in the context of using a delegate for the type of an event, the convention is to use EventHandler (where T inherits EventArgs):
一般来说,它们是等价的。但是在对事件类型使用委托的上下文中,约定是使用 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));
}
}
回答by Jason Kleban
You could have written these Action and Func generic delegates yourself, but since they're generally useful they wrote them for you and stuck them in .Net libraries.
您可以自己编写这些 Action 和 Func 泛型委托,但由于它们通常很有用,因此他们为您编写了它们并将它们放在 .Net 库中。
回答by Ivaylo Slavov
The following two lines of code are almost equivalent:
下面两行代码几乎是等价的:
public event Action<EmployeeEventAgs> Leave;
compared to:
相比:
public event EventHandler<EmployeeEventAgs> Leave;
The difference is in the signature of the event handler method. If you use the first approach with the action, you could have:
不同之处在于事件处理程序方法的签名。如果您在操作中使用第一种方法,您可以:
public void LeaveHandler(EmployeeEventAgs e) { ... }
and then this:
然后这个:
obj.Leave += LeaveHandler;
With the second approach, the signature of the LeaveHandler
needs to be different:
使用第二种方法,LeaveHandler
需要的签名不同:
public void LeaveHandler(object sender, EmployeeEventAgs e) { ... }
It is very importantto notice that in both cases the event
keyword is used to declare the event member. An event member declared this way is not simply a field of the class, despite it looks as if it was. Instead, the compiler creates it as an event property1. The event properties are similar to regular properties, except that they do not have get
or set
accessors. The compiler allows them to be used only on the left side of a +=
and -=
assignments (adding or removing an event handler). There is no way to overwrite the already assigned event handlers, or to invoke the event outside the class that declaresit.
这是非常重要的注意,在这两种情况下,event
关键字用于声明事件成员。以这种方式声明的事件成员不仅仅是类的一个字段,尽管它看起来好像是。相反,编译器将其创建为事件属性1。事件属性类似于常规属性,只是它们没有get
或set
访问器。编译器只允许在 a+=
和-=
赋值的左侧使用它们(添加或删除事件处理程序)。没有办法覆盖已经分配的事件处理程序,或者在声明它的类之外调用事件。
If the event keyword was missing in both examples, you could do the following operations with no error or warning:
如果两个示例中都缺少 event 关键字,则可以执行以下操作而不会出现错误或警告:
obj.Leave = LeaveHandler;
which will erase any registered handlersand replace them withe the LeaveHandler
.
这将删除所有已注册的处理程序并将它们替换为LeaveHandler
.
In addition, you can also perform this call:
此外,您还可以执行此调用:
obj.Leave(new EmployeeEventAgs());
The two situations above are considered an anti-pattern, if you intend to create an event. An event should be invoked only by the owner objectand should not allow for untraceableremoval of subscribers. The event
keyword is the .NET's programmatic construct that helps you stick with the correct use of events.
如果您打算创建事件,则上述两种情况被视为反模式。事件只能由所有者对象调用,并且不允许不可追踪地删除订阅者。该event
关键字是.NET的编程结构,它可以帮助你坚持正确的使用事件。
Having the above in mind, I believe many people stick to the EventHandler
approach because it is more unlikely to use an EventHandler
without the event
keyword. Actions have wider scope of usage, they do not look as naturally when used as events. The latter is, of course, a personal opinion, as the event handler approach has probably become too hardwired in my own coding practices. Still, if actions are used properly, it is not a crime to use them for events.
考虑到上述情况,我相信很多人都坚持使用这种EventHandler
方法,因为在EventHandler
没有event
关键字的情况下使用 an 的可能性更大。动作有更广泛的使用范围,它们在使用时看起来不像事件那样自然。当然,后者是个人意见,因为在我自己的编码实践中,事件处理程序方法可能变得过于固定。尽管如此,如果动作使用得当,将它们用于事件并不是犯罪。
1An event property is what the compiler automatically generates when seeing code like this:
1事件属性是编译器在看到这样的代码时自动生成的:
event EventHandler SomeEvent
It becomes roughly the same code as the following:
它变成与以下大致相同的代码:
private EventHandler _someEvent; // notice the lack of the event keyword!
public event EventHandler SomeEvent
{
add { _someEvent += value; }
remove { _someEvent -= value; }
}
Event invocations which we write as this:
我们这样写的事件调用:
this.SomeEvent(sender, args);
are converted into this:
转换成这样:
this._someEvent(sender, args);