使用EventArgs / EventArgs <t>委托类型而不是...... </t>的事件的好处

时间:2010-06-29 19:01:29

标签: c# events

我了解使用带有签名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>

谢谢

5 个答案:

答案 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)

您已回答了自己的问题:

  • 用于维护惯例的Syntactical Sugar(少写)
  • 互操作性(使用EventHandler类型,您可以轻松地集成来自其他库的事件

总之;没有充分理由不使用它,除非你被迫(通常是因为人们没有意识到它,或者不了解它)。

答案 3 :(得分:2)

来自Pro C# 2008 and the .NET 3.5 Platform

  

当编译器处理事件关键字时,会自动提供   注册和注销方法*以及任何必要的成员   代理类型的变量**。 ...确定,事件关键字是   只需要语法糖就可以节省一些打字时间。

*这包括重载方便的+=-=运营商。

** ...已标记为private,因此无法终止。

当您使用通用的EventHandler委托时,您根本不需要写出自定义委托类型。

答案 4 :(得分:2)

我要在这里摇晃船并提出完全异端的东西。我曾经坚定地参加EventArgs阵营,因为我坚持“MS推荐这个并且它总是这样做”的心态,但随着时间的推移,我开始讨厌EventArgs。为什么呢?

  • 它促进了.NET-1.0ish编码风格,它依赖于弱类型/类型转换,让我觉得不洁净。
  • 它强制你的实现事件的类每次触发时都会用新的EventArg实例污染堆,这也让我感到不安。为什么不让我的活动给予订阅者他们需要的东西,而不是把它包装在一个对我没有任何帮助的额外课程中。
  • 订阅该事件的回调方法的签名看起来像垃圾,并且具有非常少的语义细节 - 例如object sender - 什么是发件人?!?!

我现在所做的是声明我自己的事件处理程序委托,我将它整齐地存储在我的解决方案中自己的“Delegates”文件夹以及它们自己的命名空间中。所以我的代表可以像这样驻留在自己的文件中:

namespace MyAPI.Data.Delegates
{
    public delegate void DataEventHandler<TData>(DataFeed<TData> sender, TData data);
}

事件声明现在看起来像这样:

public event DataEventHandler<TData> DataReady = delegate { };

这种方法的好处:

  • 方法签名具有更多语义细节。您知道 WHO 正在发送 WHAT
  • 保留强类型。不再将object sender投射到您认为的应该是什么。
  • 您不必new()对象并污染堆,如果您的事件频繁发生,这可能会有问题。只需将您的订户完全按照他们需要的方式传递,无论是对象引用还是值类型。
  • 通过为您的代理人使用___EventHandler命名惯例,您仍在为代码推广统一的样式,这样您的API用户就可以轻松了解您的意图。

唯一的“缺点”是,您的代码用户很难将您的事件连接到具有object sender, EventArgs e签名的现有方法。但是,这一点没有实际意义,因为如果您的事件提供了任何额外的数据(例如,您创建了自己的EventArgs子类),那么他们无论如何都必须更改方法签名(或转换为您的子类类型)。无论哪种方式,这仍然是令人讨厌的。

这就是我喜欢自己的方式。