事件模式中将EventArgs作为基类的目的是什么?

13

传统的C#通用事件包括以下参数:

(object sender, EventArgs e)

我可以使用更具体的签名为e参数实现事件,这个签名是从EventArgs派生而来的。

那么,像EventArgs这样的基类有什么用呢?我的意思是...它是空的。没有基/抽象/虚拟属性,也没有字段或其他东西。

为什么基本事件的参数不像下面这样简单呢?

(object sender, object eventArgs)

也就是说,为什么所有使用了特定事件参数的事件都是从EventArgs派生而来,而不是从简单的object派生而来?

上述问题与以下问题类似。通用形式的事件委托如下:

delegate void EventHandler<TEventArgs>(object sender, TEventArgs e)

并且对参数e没有任何限制。 但我原本期望的是类似于where TEventArgs : EventArgs这样的东西,以保持一致性...


此类是包含事件数据的类的基类,为不包含事件数据的事件提供要使用的值。请参考 文档。我相信这已经很清楚了。 - Federico Dipuma
2
@FedericoDipuma 嗯,有点像,但是 object 也可以用于那个...除了 .Empty 的事情。 - Marc Gravell
1
@MarcGavell 当然你是对的。我只是指出一个事实,就是正如文档本身所承认的那样,EventArgs 没有任何技术上的理由存在。只是为了保持继承的一致性而已。 - Federico Dipuma
这也困扰着我。为什么方法签名要基于惯例,特别是因为a)似乎没有人知道起源,b)它并不是一个非常好的惯例?我们不仅使用object,而且假定我们想传递事件源的引用。在许多情况下,源与开始无关。但如果它甚至没有强类型化并且可以是任何东西(sender可以是int),那么我看不出意义所在。我设计事件的方式与我设计任何其他类的方式相同 - 使用我需要的方法和参数。 - Scott Hannen
1
松耦合是关键。事件处理程序通常存在于与您远离的代码中,由您从未见过的程序员编写。您可以更改EventArgs类型,派生自己并添加额外字段,那个遥远的代码将继续工作,而无需重新编译。 - Hans Passant
1个回答

8

对象不会排除像int、double等值类型。这将引入装箱和拆箱问题。使用基类而不是对象的选择是为了在整个API中强制传递强类型对象。

当我看到普遍使用对象类型时,我往往会感到不安,因为它有点违背了使用强类型编程语言的初衷,你可能还不如去用javascript编程,尽管任何稍微熟悉javascript的人都知道他们正在努力实现强类型编程范式

编辑: 为了更加详细地阐述事件模型传递引用类型和值类型之间的区别。当处理事件的委托修改事件数据时,很多人经常这样做,如果传递的数据是值类型,则需要开始考虑是否更改了按值传递的副本还是原始引用到值类型,当然希望更改原始引用。在.NET事件模型中强制传递引用类型是一个非常关键的设计决策。


好的,回答很有用,但是关于我指出的像 where TEventArgs : EventArgs 这样的约束缺失怎么办?这是不是意味着微软团队在某个时候改变了对该模式的看法? - Massimiliano Kraus
不。我不明白为什么这与模式完全不一致。从API可以清楚地看出,微软希望.NET中的所有事件都通过EventArgs引用类型传递。 - Mick
3
或许如果在.NET 1.0时代就有了泛型,而不是使用EventArgs,他们可能会使用where TEventArgs : class - Mick
2
以前是 where TEventArgs : EventArgs,但当他们意识到(就像 OP 一样),它并没有太多实际意义时,他们取消了这个限制。最初的想法是让所有事件都继承自 EventArgs,这样您就可以将多种不同类型的事件订阅到单个方法中,但实际上这几乎从来不是一个好主意,现在也已经没有必要,因为有了 Lambda 的可用性。对于超级性能敏感的事件,我使用强类型发送器和任何直接适合 args 的类型,以便触发事件时不需要创建短暂的 args 对象。 - Mike Marynowski
1
不确定是何时发生的。但是,https://referencesource.microsoft.com/#mscorlib/system/eventhandler.cs 有一条注释指出:// Removed TEventArgs constraint post-.NET 4 - Denxorz
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接