声明事件的首选方式


14

我对.NET事件模型非常了解。我想我可能会误解该系统的细微差别。

当我开始将事件放入班级时,我将使用标准方式,如下所示:

public event EventHandler<MyEventArgs> MyEvent;

这意味着任何订阅该事件的人都需要类似以下方法:

void HandleThatEvent(object sender, MyEventArgs args){...}

很好,但是我发现我很少关心发送者,因此它使很多方法签名变得肿。

所以我改用声明自己的委托类型

public delegate void MyEventHandler(SomeClass argument);

它减少了混乱,但是在编写处理程序时却给我带来了一个小问题:

eventImplmentor.MyEvent += HandleThatEvent;
.
.
.
void HandleThatEvent(/*oh, um, what arguments does it take? Intellisense isn't telling me*/)

因此,我将不得不返回到委托的声明,然后再查看并回写它们,或者编译它并等待被告知。

因此,现在,我只是用ActionAction<T>或任何模板适合。

public event Action<SomeClass> MyEvent;

这样我就可以将鼠标悬停在事件上,并被告知期望的参数。

毕竟,我的问题是:是否有在C#中声明事件的最佳实践?我应该回到原来的EventHandler<T>方式还是可以Action<T>接受?


不要忘记确保将处理程序本地复制到您触发事件的位置,出于线程安全的考虑,始终希望这样做。
史努比

您可以在封装的代码中编写自己的智能的,均值的和精益的类型安全事件,但是您发布的任何内容都应遵循标准模式,否则只会使类的用户(以及显然还有一些工具)迷惑。
马丁·马特

Answers:


8

对于简单的内部事件处理,有一些您只是建议使用ActionAction<T>。我倾向于使用标准模式,包括Sender,甚至用于内部事件,因为您永远不知道何时以后才希望公开类或事件,并且我不希望为了重构事件方法而付出代价。它公开。

我确实同意您的观点,事件处理签名比简单情况下的签名要重一些,但是它经过精心设计,可以处理增量迁移,因为随着时间的流逝,可能需要更多的事件参数。总的来说,我会坚持使用标准模式,尤其是因为您如前所述,只有这样做才获得适当的IntelliSense支持。

对于它的价值,我花了一些时间提出了一个不同的事件处理模式:.NET中的事件签名-使用强类型的“发件人”吗?。此处的目标不是删除Sender,而是使它通常是强类型为TSender而不是弱类型为System.Object。效果很好;但是,这样做确实会失去IntelliSense支持,因此这是一个不幸的折衷。

总的来说,我会坚持使用标准模式,但是考虑可能更好的方法很有趣。


感谢您指出我的SO问题。非常有趣 我仍然不明白为什么发件人必须强制如此重要。大多数时候,我不在乎发件人。这只是一些任意的MS规则吗?
Matt Ellen

不,您当然可以随意声明自己的代表。始终包含发件人是.NET政策,这并不是一个坏主意。
尼尔,

@Neil:我知道有时候它很有用,但是我没有总是这样做的政策-特别是因为MS建议以事件的方式进行。我真正喜欢事件的一件事是能够使类分离。如果包含对象,那么它将再次耦合起来。如果仅仅是CLS合规性问题,那么我可以接受。
马特·艾伦

仅当您使用sender对象时,它才会再次耦合备份,否则,不使用什么作为sender的值放什么都没有关系。依赖关系仅在您需要依赖时才存在。我知道您来自哪里,如果对象发件人从地球上任何服务器的所有代码中消失了,我就不会熬夜。
尼尔,

是的,如果您确实愿意,可以将“ null”作为发送者发送。但是,通过包含发送者,事件处理程序本身可以取消订阅(如果愿意)。总体而言,我想说的是了解事件的来源通常很重要。
Mike Rosenblum
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.