事件的发送者是否应该始终是通用对象?


10

使用C#编写事件时,建议以以下形式创建委托:

delegate XEventHandler(object sender, XEventArgs e);

我的问题是关于代表的第一个论点object sender。一定要一定要通用object吗?具有类型的发送方object总是会导致与此类似的代码。

val = ((ConcreteType)sender).Property;

或者,甚至更冗长,

ConcreteType obj = sender as ConcreteType
if (obj != null) { ... }

反对强类型发送者的一种说法是,其他对象可以转发事件而不必担心类型。尽管这在GUI环境中可能有意义,但是我不确定它是否可以在GUI之外受益。

如果始终知道发送方的类(至少是抽象类)怎么办?例如,如果我实现ListChanged的一个抽象事件List类,而如果其他类要继承它(例如LinkedListArrayList),是这一切的权利界定与类型的发件人我的委托List

delegate ListChangedEventHander(List sender, ListChangedEventArgs e);

还是将常规object sender类型更改为更特定的类型会有不利影响?

Answers:


10

在这一点上,它通常是(相当强的)约定。也就是说,如果您编写的库不遵循该约定,那将很奇怪。

事件设计指南说:

不要将其object用作事件处理程序的第一个参数的类型,并将其称为sender

但是,您可能会注意到,当前指南指出,您不应为事件定义自己的自定义委托,而应尽可能使用EventHandler<T>它。

对于设计,我猜想它即使在事件的原始设计者最初未预想到的上下文中也可以促进事件处理程序的重用。


2
...……仅仅是因为Microsoft决定使他们的准则通用到足以适用于所有人,但这并不意味着其他所有人都遵循他们的准则是个好主意。“其他所有人”没有编写供数百万其他开发人员使用的代码的可能性极高。从您提供的链接中,我对建议的约2/3表示反对。
Dunk 2014年

实话实说,这个“指南”或多或少都像Windows API的匈牙利表示法。一个聪明的人出于一个很好的理由启动了它,然后其他人开始滥用它。如果有指导方针,那么在该指导方针后面最好有充分的理由。什么认为这个方针的原因是,System.Windows.Forms命名空间就是事件使用最频繁的地方,它是有意义的订阅Click的事件Button或一个CheckBox。因此,发送者必须是通用。...
sampathsris 2014年

...但是,当涉及其他更具体的功能区域时,发件人可能不必是通用类。再次参见我的Lists 的类层次结构示例。
sampathsris 2014年

11
@Dunk:这就是重点。该指南来自《框架设计指南》,该框架设计指南主要涉及他人使用的代码。不是因为它是最好的解决方案,而是因为它最不令人惊讶。这是框架的最佳选择。对于较小的库,如果用例指定明确,则适用的指导较少。微软在书的开头明确地这么说。
Magus 2014年

1
我不反对这个答案,我什至赞成它,因为它来自一个有信誉的来源。我只是说我不会使用指南。如果某个事件应该发送特定数据,那么我将仅发送特定数据。此外,如果您按预期使用它们,则事件功能也可以正常工作。
Dunk 2014年

0

提出此建议的原因是,它允许将来的更改,而这些更改不一定需要更改现有代码,尤其是公共接口。

事件机制本身仍然可以用于“ VB6”样式的事件,但是如果您需要更改签名(或者更糟:创建相同事件的新版本),则必须更改所有现有使用者。使用推荐的方法,只要较新的项目继承自现有项目,就可以在不修复现有代码的情况下更新签名。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.