为什么应该在C#中的事件(sender,EventArgs)?
已知应该声明作为参数的事件(object sender, EventArgs args)
。 为什么?
这使消费开发人员能够为多个事件编写单个事件处理程序,而不pipe发件人或事件。
编辑:为什么你需要不同的模式? 您可以inheritanceEventArgs来提供任何数量的数据,而更改模式只会使任何被迫使用这种新模式的开发人员感到迷惑和困惑。
其实这是否是最好的做事方式是有争议的。 有一种思想stream派认为,由于事件旨在将两段代码分离开来,事件处理程序获取发件人并必须知道将发件人转换为什么types以便对其执行任何操作的事实,模式。
因为对于任何callback机制来说这是一个很好的模式,不pipe语言如何。 你想知道谁发送了事件(发送者)以及与事件相关的数据(EventArgs)。
对事件传递的数据使用单个参数EventArgs,可以在将来的软件版本中将数据添加到事件中,而不会破坏现有的使用者。 您只需将新成员添加到现有的EventArgs派生类,或者使用新成员创build派生类。
否则一致性和最less突然的原则certificate使用EventArgs来传递数据。
至于发件人,在一些(但不是全部)情况下,知道发送事件的types是有用的。 对发件人参数使用除对象以外的types限制太多:这意味着其他发件人不能重用相同的事件签名。
这是一个很好的模式,以这种方式实施事件可以find发送它的东西。
也覆盖EventArgs并通过它们传递数据是最好的方法。 EventArgs是一个基类。 如果您查看调用事件的各种控件,则会覆盖EventArgs,从而为您提供有关该事件的更多信息。
即使您不需要参数来执行事件,但如果您没有在框架的第一次运行中包含这些参数,并且希望稍后添加它们,则会破坏以前的所有实现,并且必须重新编写它们。 另外,如果你创build一个框架,并分发它变得更糟,因为使用你的框架的每个人都需要重构。
Chris Anderson在框架devise指南书中说:
他只是一个模式。 通过将事件参数封装在一个类中,您可以获得更好的版本化语义。 通过有一个共同的模式
(sender, e)
很容易被学习为所有事件的签名。
有些情况主要涉及互操作性,需要偏离这种模式。
看来,这是微软逐步发展事件模型的方式。 也似乎他们也正在允许另一种方式来与“新”行动代表一起做这个变化。
“对象发送者”允许当处理器方法应该对引发事件的对象执行某些操作时,为多个对象重用一个方法,例如3个文本框可以有一个单独的处理器来重置触发文本框的文本。
EventArgs的主要优势在于,它允许重构事件信息,而无需更改订阅了这种事件的所有项目中的所有处理程序的签名。
我想不出一个更聪明的办法来处理事件。
有时候,你想要强制所有的事件使用者使用特定的事件参数,例如,传递布尔参数的安全事件,真好,假坏。 在这种情况下,您希望消费者对新参数感到痛苦,即您希望消费者与该参数耦合。 请注意,您的消费者仍然与您的事件解除课程脱钩,但不是来自您的事件。
我怀疑这种情况适用于大量的情况,在这种情况下,EventArgs的价值大大降低。
单独的EventArgs类是无用的,因为它必须被派生为用任何内容实例化。 这将表明应该使用一个子类,许多已经存在于.NET中。 可悲的是,我找不到任何好的通用的。
假设你想把日志委托给一个通用的事件…而不用写你自己的EventArgs子类。 这似乎是一个毫无意义的练习,但我喜欢使用现有的function。 你可以通过Objectparameter passing你的string,但这是违背了它的使用目的。 尝试在Google上findEventArgs子类的很好的参考,然后你就干掉了。 (至less我做了。)
ReSharper有点帮助,因为当你键入“EventArgs”时,你会看到包含string“EventArgs”的所有类的列表(在你的使用/导入范围内)。 仔细查看列表,您将看到许多没有string成员的类。 当你到达ControlEventArgs的时候 ,你会发现Text属性可能被使用,但是有一个windows控件的所有开销。 ConvertEventArgs可能是有用的,因为您将types与数据一起传递,但是这仍然需要紧密的耦合,这既没有被充分logging,也没有固有的types安全。 DataReceivedEventArgs没有实现。 EntryWrittenEventArgs需要带有字节数组或StreamingContext的EventLogEntry数据。 如果您不介意在内部调用所有日志事件Exception ErrorEvents,则ErrorEventArgs更接近exception消息。 FileSystemEventArgs可能是最接近的,如果你知道你在做什么,两个string和一个必需的WatcherChangeTypes枚举参数可以设置为0。 LabelEditEventArgs使用一个int和一个string,如果你不介意需要Windows.Forms命名空间。 RenamedEventArgs类似于带有额外string的FileSystemEventArgs。 最后,System.Runtime.InteropServices中的ResolveEventArgs传递一个string。 还有其他的图书馆,但我坚持一些最常见的图书馆。 所以,根据实现,我可以使用ErrorEventArgs , FileSystemEventArgs或ResolveEventArgs进行日志logging。