【问题标题】:Are there compelling reasons to use EventHandler<T> delegate instead of just Action<T> when declaring events?声明事件时是否有令人信服的理由使用 EventHandler<T> 委托而不仅仅是 Action<T>?
【发布时间】:2012-06-06 20:30:34
【问题描述】:

当我声明一个事件时,我一直在使用Action 委托或Action&lt;T, ...&gt; 委托(如果事件处理程序有参数)。我最近注意到EventHandler 委托的存在,它需要一个继承EventArgs 的类型参数。后一种方法要求我创建一个附加类,该类仅用于封装随事件传递的任何参数,这似乎没有必要,除非我遗漏了什么。

那么,在声明事件时使用EventArgs 委托的原因是什么?它能给我带来什么?

【问题讨论】:

    标签: c# .net events delegates


    【解决方案1】:

    它使您能够返回事件参数,仅此而已。如果您不需要,那么也许您不需要EventHandler 代表。

    从更大的角度来看,EventArgs 是使用事件将数据从一个地方获取到另一个地方的“社会可接受的”方式。当然,您可以创建自定义委托来执行此操作,但 EventArgs 在 Visual Studio 等中有工具支持。

    【讨论】:

      【解决方案2】:

      它为您提供了一个可扩展点,以便将来更改您的活动。

      假设我定义了一个类Car

      public class Car { 
          String Make { get; set; }
          String Model { get; set; }
          int Year { get; set; }
      }
      

      还有一个事件CarBuilt

      public event Action<Car> CarBuilt;
      

      没关系。但是,如果我希望以后的活动包括制造汽车的人呢?使用操作,我需要更改事件签名或将该信息添加到 Car 类(它确实不属于该类)。

      如果我这样定义它:

      public class CarBuiltEventArgs : EventArgs {
          public Car TheCar { get; set; }
      }
      
      public event EventHandler<CarBuiltEventArgs> CarBuilt;
      

      然后我可以将 BuiltBy 属性添加到 CarBuiltEventArgs 类中,一切就绪。

      public class CarBuiltEventArgs : EventArgs {
          public Car TheCar { get; set; }
          public String BuiltBy { get; set; }
      }
      

      【讨论】:

        【解决方案3】:

        您表示如果需要参数,您将使用 Action。比较两者,问问自己,如果明年您的需求发生变化并且您需要在该事件中传递一个新参数,那么需要什么?您是更改大量代码还是仅更改一个继承 EventArgs 的类?

        【讨论】:

          【解决方案4】:

          使用EventHandler&lt;T&gt; 的最大原因可能是不同类型的委托——即使这些类型使用相同的方法签名——也不能互换。如果一个事件使用EventHandler&lt;fnordEventArgs&gt; 而另一个使用Action&lt;Object, fnordEventArgs&gt;,则可以为这两个事件订阅相同的方法,但为一个事件创建的委托不能与另一个事件一起使用。通常,这没什么大不了的,因为像FirstEvent += methodName 这样的语句会翻译成FirstEvent += new EventHandler&lt;fnordEventArgs&gt;(methodName),而SecondEvent += methodName 会翻译成FirstEvent += new Action&lt;Object, fnordEventArgs&gt;(methodName)。然而,在某些情况下,事件订阅者需要存储用于订阅的委托。对于存储委托的订阅者,它必须正确地知道它的类型。始终使用EventHandler&lt;T&gt; 作为void EventHandler(Object sender, T args) 形式的事件处理方法的委托,可以更轻松地创建正确的委托类型。

          【讨论】:

            猜你喜欢
            • 2011-01-17
            • 1970-01-01
            • 1970-01-01
            • 2014-06-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多