我了解使用带有签名delegate void delegate_name(object sender, EventArgs e)
a)但除了可以为我们节省一些打字这一事实之外,还有其他原因我们应该使用已定义的委托类型EventHandler/EventHandler<T>
而不是使用签名delegate void delegate_name(object sender, EventArgs e)
声明我们自己的委托类型吗?
b)我可以考虑使用预定义委托类型EventArgs/EventArgs<T>
的另外两个原因是:
消费特定事件的人(比如说event EventHandler my_event
)会立即知道如何使用该事件吗?
也许一些流行的第三方方法接受参数EventHandler/ EventHandler<T>
委托类型,因此如果我们的代码有可能使用这些第三方方法,我们应该使用预定义的委托EventHandler/Eventhandler<T>
?
谢谢
答案 0 :(得分:11)
对我来说,这个问题有点奇怪。否则这样做会带来什么好处(定义与某些EventHandler<TEventArgs>
完全匹配TEventArgs
的委托类型)?
也就是说,至少一个的好处我可以想到以“正常”的方式做到这一点:某些API已经期望与EventHandler<TEventArgs>
代表打交道;例如,Rx Extensions包含一个如下所示的方法:
Observable.FromEvent<TEventArgs>(
Action<EventHandler<TEventArgs>> addHandler,
Action<EventHandler<TEventArgs>> removeHandler
);
如果您定义了自己的委托,那么使用这样的方法 - 期望EventHandler<TEventArgs>
委托 - 会变得比必要的更复杂,没有任何额外的好处(无论如何我都可以看到)。
答案 1 :(得分:7)
你忘记了一个重要的人:
答案 2 :(得分:5)
您已回答了自己的问题:
EventHandler
类型,您可以轻松地集成来自其他库的事件总之;没有充分理由不使用它,除非你被迫(通常是因为人们没有意识到它,或者不了解它)。
答案 3 :(得分:2)
来自Pro C# 2008 and the .NET 3.5 Platform:
当编译器处理事件关键字时,会自动提供 注册和注销方法*以及任何必要的成员 代理类型的变量**。 ...确定,事件关键字是 只需要语法糖就可以节省一些打字时间。
*这包括重载方便的+=
和-=
运营商。
** ...已标记为private
,因此无法终止。
当您使用通用的EventHandler委托时,您根本不需要写出自定义委托类型。
答案 4 :(得分:2)
我要在这里摇晃船并提出完全异端的东西。我曾经坚定地参加EventArgs
阵营,因为我坚持“MS推荐这个并且它总是这样做”的心态,但随着时间的推移,我开始讨厌EventArgs
。为什么呢?
EventArg
实例污染堆,这也让我感到不安。为什么不让我的活动给予订阅者他们需要的东西,而不是把它包装在一个对我没有任何帮助的额外课程中。object sender
- 什么是发件人?!?!我现在所做的是声明我自己的事件处理程序委托,我将它整齐地存储在我的解决方案中自己的“Delegates”文件夹以及它们自己的命名空间中。所以我的代表可以像这样驻留在自己的文件中:
namespace MyAPI.Data.Delegates
{
public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}
事件声明现在看起来像这样:
public event DataEventHandler<TData> DataReady = delegate { };
这种方法的好处:
object sender
投射到您认为的应该是什么。new()
对象并污染堆,如果您的事件频繁发生,这可能会有问题。只需将您的订户完全按照他们需要的方式传递,无论是对象引用还是值类型。___EventHandler
命名惯例,您仍在为代码推广统一的样式,这样您的API用户就可以轻松了解您的意图。唯一的“缺点”是,您的代码用户很难将您的事件连接到具有object sender, EventArgs e
签名的现有方法。但是,这一点没有实际意义,因为如果您的事件提供了任何额外的数据(例如,您创建了自己的EventArgs
子类),那么他们无论如何都必须更改方法签名(或转换为您的子类类型)。无论哪种方式,这仍然是令人讨厌的。
这就是我喜欢自己的方式。