3 回答
TA贡献1765条经验 获得超5个赞
EventHandler
是类型的委托void EventHandler(object sender, EventArgs e)
。所以订阅事件的处理程序的签名必须与此匹配。
Nowvoid OnTableChanged(SqlChangeNotifier sender, SqlNotificationEventArgs e)
比这更具体:它不能再接受任何 sender
对象,并且事件参数也必须是 type SqlNotificationEventArgs
。
现在的问题是,当引发事件时,事件的原始发送者将尝试使用参数调用事件处理程序,object sender, EventArgs e
但您的方法需要更专业的类型。类型系统无法保证这些参数实际上是那些专用类型。
如果您需要这些类型,则需要将事件类型更改为限制性更强的委托类型。
TA贡献1853条经验 获得超6个赞
有关此类更改的总体主题,请参阅逆变和协方差。
请记住,事件系统只是调用一系列方法的奇特方式,您可以在运行时换出这些方法,因此如果您不能使用与引发事件时传递的完全相同的参数直接调用处理程序,那么事件系统也做不到。
与方法一样,事件处理程序是逆变的,这意味着类型的委托EventHandler<SpecializedEventArgs>(假设SpecializedEventArgs : EventArgs)将接受签名处理程序,public void Handler(object sender, EventArgs args)因为对事件的调用最终会使用对象调用处理程序,该SpecializedEventArgs对象可以EventArgs通过简单的多态性隐式转换为。IE以下将编译:
public static event EventHandler<SpecializedEventArgs> Event;
public static void Handler(object sender, EventArgs args) { }
public static void Main() {
Event += Handler;
//...
TA贡献1805条经验 获得超9个赞
你不能那样做,因为事件的订阅者应该得到一个派生实例,但发布者只能提供一个基础实例。
你可以做相反的事情:
public static event KeyEventHandler ChangeDetected; // handler with derived args signature
private static void Program_ChangeDetected(object sender, EventArgs e) // base event args are OK
{
Console.WriteLine("ChangeDetected");
}
static void Main(string[] args)
{
ChangeDetected += Program_ChangeDetected;
ChangeDetected?.Invoke(null, new KeyEventArgs(default)); // base event args are NOT OK
}
- 3 回答
- 0 关注
- 79 浏览
添加回答
举报