【问题标题】: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<T, ...> 委托(如果事件处理程序有参数)。我最近注意到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<T> 的最大原因可能是不同类型的委托——即使这些类型使用相同的方法签名——也不能互换。如果一个事件使用EventHandler<fnordEventArgs> 而另一个使用Action<Object, fnordEventArgs>,则可以为这两个事件订阅相同的方法,但为一个事件创建的委托不能与另一个事件一起使用。通常,这没什么大不了的,因为像FirstEvent += methodName 这样的语句会翻译成FirstEvent += new EventHandler<fnordEventArgs>(methodName),而SecondEvent += methodName 会翻译成FirstEvent += new Action<Object, fnordEventArgs>(methodName)。然而,在某些情况下,事件订阅者需要存储用于订阅的委托。对于存储委托的订阅者,它必须正确地知道它的类型。始终使用EventHandler<T> 作为void EventHandler(Object sender, T args) 形式的事件处理方法的委托,可以更轻松地创建正确的委托类型。