为了账号安全,请及时绑定邮箱和手机立即绑定

无法为 C# 中的 EventArgs 分配使用派生类型的事件处理程序

无法为 C# 中的 EventArgs 分配使用派生类型的事件处理程序

C#
倚天杖 2022-12-24 14:17:23
所以我有一个事件声明如下:public event EventHandler OnChangeDetected;然后我将以下处理程序分配给该事件。myObject.OnChangeDetected += OnTableChanged;我的理解是,此类事件需要我的 OnTableChanged 方法具有以下可以正常编译的签名。public void OnTableChanged(object sender, EventArgs e)现在我想将 OnTableChanged 事件替换为以下签名。public void OnTableChanged(SqlChangeNotifier sender, SqlNotificationEventArgs e)但是,当我用派生类型替换参数时,它会抱怨没有与委托 EventHandler 匹配的“OnTableChanged”重载。由于 SqlChangeNotifier 派生自 Object,而 SqlNotificationEventArgs 派生自 EventArgs,谁能解释为什么我不能拥有这些派生参数类型,因为它们继承自正确的基类型?
查看完整描述

3 回答

?
POPMUISE

TA贡献1765条经验 获得超5个赞

EventHandler是类型的委托void EventHandler(object sender, EventArgs e)。所以订阅事件的处理程序的签名必须与此匹配。

Nowvoid OnTableChanged(SqlChangeNotifier sender, SqlNotificationEventArgs e)比这更具体:它不能再接受任何 sender对象,并且事件参数也必须是 type SqlNotificationEventArgs

现在的问题是,当引发事件时,事件的原始发送者将尝试使用参数调用事件处理程序,object sender, EventArgs e但您的方法需要更专业的类型。类型系统无法保证这些参数实际上是那些专用类型。

如果您需要这些类型,则需要将事件类型更改为限制性更强的委托类型。


查看完整回答
反对 回复 2022-12-24
?
墨色风雨

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;

//...


查看完整回答
反对 回复 2022-12-24
?
Cats萌萌

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

}


查看完整回答
反对 回复 2022-12-24
  • 3 回答
  • 0 关注
  • 79 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信