繁体   English   中英

为什么C#中的事件需要(sender,EventArgs)?

[英]Why should events in C# take (sender, EventArgs)?

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

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

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

实际上,这是否是做事件的最佳实践方式是有争议的。 有一种思想流派,因为事件旨在将两段代码分离,事件处理程序获取发送者这一事实,并且必须知道将发送者强制转换为什么类型才能对其执行任何操作。图案。

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

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

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

至于发送者,在某些(但不是全部)情况下,知道发送事件的类型是有用的。 对于sender参数使用除object之外的类型限制太多:这意味着其他发件人无法重用相同的事件签名。

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

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

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

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

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

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

这似乎是微软随着时间的推移演变事件模型的方式。 似乎他们也允许采用另一种方式来实现“新”行动代表及其变体。

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

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

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

有时您希望强制所有事件使用者使用特定的事件参数,例如,传递布尔参数的安全事件,true表示良好,false表示错误。 在这种情况下,您希望消费者能够痛苦地了解新参数,即您希望消费者与该参数相结合。 请注意,您的消费者仍然与您的活动解雇课程脱钩,但不会与您的活动脱钩。

我怀疑这种情况适用于大量案例,在这种情况下,EventArgs的值大大减少。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM