C# 为什么MSDN建议在委托声明中包含对象发送者?

C# 为什么MSDN建议在委托声明中包含对象发送者?,c#,events,delegates,C#,Events,Delegates,我正在阅读这一页,我注意到它说这是标准指南: NET Framework指南指出,用于事件的委托类型应采用两个参数,一个是表示事件源的“object source”参数,另一个是封装有关事件的任何附加信息的“e”参数 我可以理解,在某些情况下,拥有一个对象发送器是多么有用,但在其他情况下,我可以看到完全相反的情况。比如说, 如果处理事件的类不应该知道是谁触发了它,该怎么办?耦合、内聚以及所有这些 在我的例子中,我已经将对象作为成员变量引用。这就是我订阅活动的方式。它只有一个实例,因此没有理由强制

我正在阅读这一页,我注意到它说这是标准指南:

NET Framework指南指出,用于事件的委托类型应采用两个参数,一个是表示事件源的“object source”参数,另一个是封装有关事件的任何附加信息的“e”参数

我可以理解,在某些情况下,拥有一个
对象发送器是多么有用,但在其他情况下,我可以看到完全相反的情况。比如说,

  • 如果处理事件的类不应该知道是谁触发了它,该怎么办?耦合、内聚以及所有这些

  • 在我的例子中,我已经将对象作为成员变量引用。这就是我订阅活动的方式。它只有一个实例,因此没有理由强制转换发送者对象,而不仅仅是使用成员变量

  • 在我的程序中,客户端根本不应该知道发送方对象。很难解释我在做什么,但基本上我在一个库中有一个具有内部构造函数的类,该库中还有另外两个类使用该类。我的客户机类订阅这两个类中的事件,但是这些事件最初是从客户机不应该知道的这个内部类调用的

  • 这会使事件处理程序的客户端感到困惑。库应该易于理解,在我的例子中,没有理由使用sender变量。没有一个那为什么要包括它呢

  • 也就是说,为什么Microsoft指出事件处理程序应该遵循这些准则?这不总是最好的选择吗


    编辑:谢谢大家的回复。我决定与大多数人一起使用
    EventHandler
    来处理这个库中的所有事件。

    我认为这种模式的原因是为了实现某种一致性。sender参数允许对多个发布服务器(按钮、表)重复使用单个处理程序

    针对您的观点:

    1) 只是不要使用它。这是很常见的,并不会损害任何良好的实践

    2) 没关系,再次忽略发件人

    3) 与你在2)项下所说的完全矛盾。
    其余部分与1)相同。您甚至可以考虑将<代码> null <代码>作为发送器。 4) “那么为什么要包括它”——还有其他用例确实需要发送者


    但请注意,这只是图书馆确认BCL的指南。

    您的案例听起来更像是一个特定的应用程序(而不是库),所以可以随意使用任何您喜欢的参数方案。编译器不会抱怨的

    这样的指导原则允许事件消费者的可预测性。它还允许处理您在创建事件时可能从未考虑过的其他场景,特别是当您的库被第三方开发人员使用时


    它允许处理事件的方法始终手头有正确的对象实例,以及有关触发事件原因的基本信息。

    您正在迎风而战,.NET framework有一定的设计、规则和指导原则,在使用它时,如果您想正确使用它,你应该按照这些指示去做

    如果使用原始委托,则可以获得所需的所有自由,但如上所述,如果要为事件声明委托类型,则应包括
    sender
    对象和
    EventArgs
    对象(基本类或派生类)

    如果您违反了这些规则,正如我刚才在回答您的另一个问题时所说的那样:您可能最终会遇到代码中断的情况

    最简单的是,当框架调用控件上的OnClick事件时,.NET framework会传递发送方和
    EventArgs
    实例。。。如果该事件不符合要求,则可能会出现故障


    如果您想要完全自由,那么使用简单的委托,而不是事件。

    这只是一种良好的做法,但只要您不需要知道触发事件的对象或与该对象相关的任何其他信息,就可以了。我总是把它包括在内,因为你永远不知道什么时候你会需要它


    我的建议是坚持下去,这一点也不有害。

    首先,重要的是要注意,指导方针不是法律

    如果你不遵循这些指导原则,那么所有的地狱(或与程序员相当的地狱)都不会一败涂地

    因此,您可以随意适当地更改活动的签名

    然而,同样重要的是要知道为什么要添加这些指导原则,这个问题的答案的一大部分是版本控制

    由以下两部分组成,并且只有这两部分:

  • 事件的源,尽可能键入为“泛型”(注意,事件签名早在适当的泛型引入系统之前就已经设计好了,因此
    对象
    在当时是通用的)
  • EventArgs
  • 然后,您正在设计对更改更具弹性的代码

    首先,由于不“允许”添加或删除参数,因此事件的所有未来版本仍然只有
    sender
    e

    其次,关于
    e
    参数,指南还有第二部分。如果您在类库的新版本中决定通过更改
    e
    参数的类型来更改事件处理程序的签名,则应该通过从当前类型降序并传递子代来使其更具体

    原因是已经处理当前(旧)类型的现有代码仍然可以工作

    因此,该指南背后的全部理由是:

  • 保持一致(就像别人对我一样)