在一个类中打包事件参数,为什么?

Dan*_*dor 24 .net c# events

大多数.NET股票事件都有这个签名:

delegate void SomethingSomething(SomethingEventArgs e);
event SomethingSomething OnSomethingSomething;
Run Code Online (Sandbox Code Playgroud)

class SomethingEventArgs
{
    public string Name;
    public int Index;
    public double Groar;
}
Run Code Online (Sandbox Code Playgroud)

为什么这更好(显然是,否则任何人都会选择做)比:

delegate void SomethingSomething(string Name, int Index, double Groar);
event SomethingSomething OnSomethingSomething;
Run Code Online (Sandbox Code Playgroud)

因为你不必将参数打包到一个对象,并且没有初始化器(.NET 2.0),它就是一种打字练习.

我想到的一个原因是,当你将它们打包在一个对象中时,你可以更简单地返回你的值 - 即.handler可以修改对象的成员.但是,对于多播事件,无论如何都不总是好的.

所以为什么?

jga*_*fin 30

阅读开放/封闭原则.

通过使用类,所有继承的类都可以引入额外的功能,而无需更改委托签名.他们可以简单地引入一个新的事件类(ExtendedEventArgs)继承你的(SomeEventArgs).


Bas*_*ter 15

主要原因是它更易于维护.如果传递对象并且任何属性发生更改,则只需修改它.如果你传递变量,那就更多了.因此,代码以这种方式变得更易于维护和可读性.

微软代码完整的引用:

将例程参数的数量限制为大约7.七是人们理解的神奇数字.心理学研究发现,人们通常无法同时跟踪超过七个大块的信息(Miller 1956).这一发现已经应用于大量学科,并且似乎可以安全地推测大多数人不能同时跟踪超过七个常规参数.

实际上,限制参数数量的程度取决于语言处理复杂数据类型的方式.如果使用支持结构化数据的现代语言编程,则可以传递包含13个字段的复合数据类型,并将其视为数据的一个心理"块".如果使用更原始的语言编程,则可能需要单独传递所有13个字段,

如果你发现自己经常传递多个参数,那么你的例程之间的耦合就太紧了.设计例程或一组例程以减少耦合.1f您将相同的数据传递给许多不同的例程,将例程分组到一个类中,并将常用数据视为类数据.

来自原始帖子图像的引用文本


Luk*_*oid 11

这样做的原因是为了避免破坏变化.例如,您的班级可能希望在其事件中包含更多信息,但是当代理不再匹配时,使用该事件的每个事物都会中断.通过拥有严格的委托,您的事件可以在将来封装更多信息,而不会影响任何订阅者.

编辑:根据评论,我将扩展它如何影响减少破坏性变化.

如果我们希望在我们引发的事件中添加更多信息,EventArgs则可以添加从新属性/方法派生的单个类.这意味着事件的任何现有订阅者都不需要更改,因为添加这些属性不会影响它们.唯一需要的更改是设置/使用这些属性的位置,例如引发事件的位置.

  • @StevenJeuris如果我在派生的`EventArgs`类中添加了更多属性,则只会影响此类的实例化(最有可能是事件被引发的地方),任何现有的侦听器都只会使用以前存在的属性并忽略这些新属性,消除任何重大变化. (3认同)

Ric*_*ard 9

好处是模式; 并且具有模式提供了一致性以及跨多种事件类型使用其他API的能力:

  • EventHandler<T>委托类型(你不需要定义自己的委托类型).
  • Reactive Extensions(Rx)将事件转换为IObservable<T>允许在事件源上使用LINQ Observable.FromEvent.

你的签名也错了:

  • 委托有两个参数:object sourceSomethingEventArgs
  • SomethingEventArgs类型继承EventArgs.

因此,您的代码应该是模式的示例:

在命名空间范围:

public class SomethingEventArgs : EventArgs {
    public string Name;
    public int Index;
    public double Groar;
}

public delegate void SomethingSomething(object source, SomethingEventArgs e);
Run Code Online (Sandbox Code Playgroud)

并在暴露类型的类型

public event SomethingSomething OnSomethingSomething;
Run Code Online (Sandbox Code Playgroud)

(事件也可能是internal.)

  • @DanielMošmondor"简化"删除了模式和要点. (4认同)

And*_*bel 6

正如其他人所指出的那样,存在可维护性和一致性的原因.EventArgs方法还使事件处理程序可以修改 EventArgs.

修改EventArgs的一个原因是错误处理.在后台线程上捕获的异常作为事件传递给客户端.客户端可以在EventArgs中设置一个标志,以指示处理的异常不应该在后台线程上重新抛出.

另一个例子是ObjectDataSource允许客户端在需要时提供对象实例的类.这是通过订阅ObjectDataSource.ObjectCreating事件并通过设置EventArgs的成员来提供对象实例来完成的.