40

众所周知,您应该声明以参数为参数的事件(object sender, EventArgs args)。为什么?

4

10 回答 10

22

这使消费开发人员能够为多个事件编写单个事件处理程序,而不管发送者或事件如何。

编辑:为什么你需要不同的模式?您可以继承 EventArgs 以提供任意数量的数据,而更改模式只会使任何被迫使用这种新模式的开发人员感到困惑和沮丧。

于 2008-09-19T19:16:27.913 回答
11

实际上,这是否是进行活动的最佳实践方式是有争议的。有一种学派认为,由于事件旨在解耦两段代码,事件处理程序获取发送者,并且必须知道将发送者转换为什么类型才能对其进行任何处理这一事实是反图案。

于 2008-09-19T19:40:47.760 回答
6

因为无论语言如何,它都是任何回调机制的好模式。您想知道谁发送了事件(发送者)以及与事件相关的数据(EventArgs)。

于 2008-09-19T19:18:48.390 回答
5

对事件传递的数据使用单个参数 EventArgs 允许您在软件的未来版本中将数据添加到事件中,而不会破坏现有消费者。您只需将新成员添加到现有 EventArgs 派生类,或使用新成员创建派生类。

否则,一致性和最小意外原则证明使用 EventArgs 传递数据是合理的。

至于发送者,在某些(但不是全部)情况下,了解发送事件的类型很有用。为 sender 参数使用 object 以外的类型过于严格:这意味着其他发送者无法重用相同的事件签名。

于 2008-09-19T20:04:45.957 回答
2

这是一个很好的使用模式,这样任何实现事件的人都可以找到发送它的内容。

覆盖 EventArgs 并通过它们传递数据也是最好的方法。EventArgs 是一个基类。如果您查看调用事件的各种控件,它们会覆盖 EventArgs,从而为您提供有关事件的更多信息。

即使您不需要参数来执行事件,如果您没有将它们包含在框架的第一次运行中并且想要稍后添加它们,那么您会破坏所有先前的实现,并且必须重新编写它们。另外,如果您创建一个框架并要分发它会变得更糟,因为使用您的框架的每个人都需要重构。

于 2008-09-19T19:22:28.197 回答
2

Chris Anderson 在《框架设计指南》一书中说:

[T]这只是一个模式。通过将事件参数打包在一个类中,您可以获得更好的版本控制语义。通过拥有一个共同的模式(sender, e),它很容易被学习为所有事件的签名。

有些情况主要涉及互操作,需要偏离这种模式。

于 2008-09-19T20:49:34.990 回答
1

这似乎是微软随着时间的推移演变事件模型的方式。似乎他们还允许使用另一种方式来使用“新”Action 委托及其变体来做到这一点。

于 2008-09-19T19:20:24.643 回答
0

有时您希望强制所有事件使用者使用特定事件参数,例如,传递布尔参数的安全事件,true 表示好,false 表示坏。在这种情况下,您希望您的消费者痛苦地意识到新参数,即您希望您的消费者与该参数耦合。请注意,您的消费者仍然与您的事件触发类分离,但与您的事件无关。

我怀疑这种情况适用于大量情况,在这些情况下,EventArgs 的值会大大降低。

于 2009-11-02T03:05:45.423 回答
0

当处理程序方法应该对引发事件的对象执行某些操作时,“对象发送者”允许为多个对象重用一种方法,例如 3 个文本框可以有一个处理程序来重置触发文本框的文本。

EventArgs 的主要优点是它允许重构事件信息,而无需更改订阅此类事件的所有项目中的所有处理程序的签名。

我想不出更聪明的方式来处理事件。

于 2011-07-05T08:34:22.350 回答
-1

单独的EventArgs类是无用的,因为它必须派生以使用任何内容进行实例化。这表明应该使用一个子类,并且许多子类已经存在于 .NET 中。可悲的是,我找不到任何好的通用的。

假设您想将日志记录委托给通用事件...而不编写您自己的 EventArgs 子类。这似乎是一个毫无意义的练习,但我喜欢使用现有的功能。您可以通过 Object 参数传递您的字符串,但这违背了它的预期用途。尝试在 Google 上找到 EventArgs 子类的一个很好的参考,你会干的。(至少我做到了。)

ReSharper 有点帮助,因为当您键入“EventArgs”时,您会看到包含字符串“EventArgs”的所有类的列表(在您的使用/导入范围内)。仔细阅读列表,您会看到许多没有字符串成员的类。当您到达ControlEventArgs时,您会看到可能会使用 Text 属性,但会产生 Windows 控件的所有开销。 ConvertEventArgs可能很有用,因为您将类型与数据一起传递,但这仍然需要紧密耦合,既没有很好的文档记录,也没有本质上的类型安全。 DataReceivedEventArgs没有实现。 EntryWrittenEventArgs需要一个带有字节数组的 EventLogEntry 或数据的 StreamingContext。 错误事件参数如果您不介意在内部调用所有日志事件 Exception ErrorEvents ,则更接近,带有异常消息。 FileSystemEventArgs可能是最接近的,有两个字符串和一个必需的 WatcherChangeTypes 枚举参数,如果您知道自己在做什么,可以将其设置为 0。 如果您不介意需要 Windows.Forms 命名空间, LabelEditEventArgs使用一个 int 和一个字符串。RenamedEventArgs类似于具有额外字符串的 FileSystemEventArgs。最后, System.Runtime.InteropServices 中的ResolveEventArgs传递一个字符串。还有其他库,但我坚持使用一些最常见的库。因此,根据实现我可以使用ErrorEventArgs用于记录的FileSystemEventArgsResolveEventArgs 。

于 2011-03-14T18:15:20.957 回答