为什么 C# 中的事件应该采用 (sender, EventArgs)?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/104674/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 14:09:51  来源:igfitidea点击:

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

提问by ripper234

It's known that you should declare events that take as parameters (object sender, EventArgs args). Why?

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

采纳答案by Greg Hurlman

This allows the consuming developer the ability to write a single event handler for multiple events, regardless of sender or event.

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

Edit:Why would you need a different pattern? You can inherit EventArgs to provide any amount of data, and changing the pattern is only going to serve to confuse and frustrate any developer that is forced to consume this new pattern.

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

回答by Eric Z Beard

Because it's a good pattern for any callback mechanism, regardless of language. You want to know who sent the event (the sender) and data that is pertinent to the event (EventArgs).

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

回答by casademora

It seemed that this was Microsoft's way to evolve the event model over time. It also seems that they are also allowing another way to do it with the "new" Action delegate and it's variations.

这似乎是 Microsoft 随时间演变事件模型的方式。似乎他们还允许以另一种方式使用“新”动作委托及其变体来实现。

回答by David Basarab

It is a good pattern to use, that way what ever implements the event can find what was sending it.

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

Also overriding the EventArgs and passing data through them is the best method. The EventArgs are a base class. If you look at various controls that call events, they have overridden EventArgs which gives you more information about the event.

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

Even if you don't need the arguments to do the event, if you do not include them with the first run of the framework and want to add them later, you break all previous implementations, and have to re-write them. Plus if you a creating a framework and going to distribute that it becomes worse because everybody that uses your framework will need to refactor.

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

回答by user6288

Actually this is debatable whether or not this is the best practice way to do events. There is the school of thought that as events are intended to decouple two segments of code, the fact that the event handler gets the sender, and has to know what type to cast the sender into in order to do anything with it is an anti-pattern.

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

回答by Joe

Using a single parameter, EventArgs, for the data passed by an event allows you to add data to your event in future versions of your software without breaking existing consumers. You simply add new members to an existing EventArgs-derived class, or create a derived class with the new members.

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

Otherwise consistency and the principle of least surprise justify using EventArgs for passing data.

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

As for sender, in some (but not all) cases it's useful to know what type sent the event. Using a type other than object for the sender argument is too restrictive: it would mean that other senders couldn't reuse the same event signature.

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

回答by fryguybob

Chris Anderson says in the Framework Design Guidelines book:

Chris Anderson 在 Framework Design Guidelines 一书中说:

[T]his is just about a pattern. By having event arguments packaged in a class you get better versioning semantics. By having a common pattern (sender, e)it is easily learned as the signature for all events.

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

There are situations mostly involving interop that would require deviation from this pattern.

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

回答by Dean

Sometimes you would like to force all of your event consumers to use a particular event parameter, for example, a security event which passes a boolean parameter, true for good, false for bad. In this case you want your consumer to be painfully aware of the new parameter, i.e. you want your consumers to be coupled with that parameter. Take note, your consumers are still decoupled from your event firing class, but not from your event.

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

I suspect that this scenario applies to a large number of cases and in those cases the value of EventArgs is greatly reduced.

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

回答by CZahrobsky

The EventArgsclass alone is useless since it must be derived to instantiate with any content. This would indicate a subclass should be used, and many already exist in .NET. Sadly, I can't find any good generic ones.

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

Let's say you want to delegate logging to a generic event... WITHOUT WRITING YOUR OWN EventArgs SUBCLASS. It may seem a pointless exercise, but I like using existing features. You can pass your string through the Object argument, but that goes against it's intended use. Try to find a good reference of EventArgs subclasses on Google, and you'll come up dry. (At least I did.)

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

ReSharper helps a bit, since when you type "EventArgs" you'll see a list of all classes (within your using/imports scope) that CONTAIN the string "EventArgs". Perusing the list you'll see many classes with no string members. When you get to ControlEventArgs, you see that the Text property might be used, but with all of the overhead of a windows control. ConvertEventArgsmight be useful, since you pass the type along with the data, but this still requires tight coupling that's neither well-documented nor inherently type-safe. DataReceivedEventArgshas no implementation. EntryWrittenEventArgsrequires an EventLogEntry with a byte array or StreamingContext for data. ErrorEventArgsis closer, with an Exception message, if you don't mind calling all of your log events Exception ErrorEvents internally. FileSystemEventArgsis probably the closest yet, with two strings and a required WatcherChangeTypes enum argument that CAN be set to 0, if you know what you're doing. LabelEditEventArgsuses an int and a string, if you don't mind requiring the Windows.Forms namespace. RenamedEventArgsis similar to FileSystemEventArgs with an extra string. Finally, ResolveEventArgsin System.Runtime.InteropServices passes a single string. There are other libraries, but I stuck to some of the most common ones. So, depending on the implementation I can use ErrorEventArgs, FileSystemEventArgsor ResolveEventArgsfor logging.

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

回答by carsten

"Object sender" allows to reuse one method for multiple objects when the handler method is supposed to do something with the object that raised the event, for example 3 textbox can have one single handler that will reset the text of the firing textbox.

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

EventArgs's main advantage is that it allows to refactor event information without the need to change signatures of all handlers in all projects that are subscribed to this kind of event.

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

I can't think of a smarter way to deal with events.

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