当我声明一个事件时,如果事件处理程序有参数,我一直在使用Action
委托或委托。Action<T, ...>
我最近注意到EventHandler
委托的存在,它需要一个继承EventArgs
. 后一种方法要求我创建一个附加类,该类仅用于封装随事件传递的任何参数,这似乎是不必要的,除非我遗漏了什么。
那么,在声明事件时使用委托的原因是什么?EventArgs
它给我买了什么?
它使您能够返回事件参数,仅此而已。如果您不需要,那么也许您不需要EventHandler
代表。
从更大的角度来看,EventArgs
这是使用事件将数据从一个地方获取到另一个地方的“社会可接受的”方式。当然,您可以创建自定义委托来执行此操作,但EventArgs
在 Visual Studio 等中具有工具支持。
它为您提供了一个可扩展点,用于在未来更改您的事件。
假设我定义了一个类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; }
}
如果需要参数,您表示您使用 Action 。比较这两者,问问自己,如果明年您的需求发生变化并且您需要在该事件中传递一个新参数,那么需要什么?您是更改大量代码还是仅更改一个继承 EventArgs 的类?
使用的最大原因EventHandler<T>
可能是不同类型的委托——即使这些类型使用相同的方法签名——也不能互换。如果一个事件使用 anEventHandler<fnordEventArgs>
而另一个使用 an Action<Object, fnordEventArgs>
,则可以为这两个事件订阅相同的方法,但为一个事件创建的委托不能与另一个事件一起使用。通常,这没什么大不了的,因为语句 likeFirstEvent += methodName
会翻译成FirstEvent += new EventHandler<fnordEventArgs>(methodName)
,并且SecondEvent += methodName
会翻译成FirstEvent += new Action<Object, fnordEventArgs>(methodName)
。然而,在某些情况下,事件订阅者需要存储用于订阅的委托。对于存储委托的订阅者,它必须正确地知道它的类型。始终EventHandler<T>
用作表单的事件处理方法的委托void EventHandler(Object sender, T args)
使得创建正确的委托类型变得更加容易。