首页 文章

为什么事件不支持绑定继承类型?

提问于
浏览
0

在这些代表中:

EventHandler

public delegate void EventHandler(object sender,EventArgs e);

FormClosingEventHandler

public delegate void FormClosingEventHandler(object sender,FormClosingEventArgs e);

FormClosingEventArgs 继承自 EventArgs . 为什么我不能用 EventHandler 委托的事件处理程序绑定 FormClosing 事件?

我知道事件处理程序的签名必须与其委托匹配,但为什么它不支持匹配继承的类型?

2 回答

  • 2

    好吧,这很有意思......

    您可以使用兼容类型的方法组转换绑定事件处理程序:

    public void GenericHandlerMethod(object sender, EventArgs e) {}
    
    ...
    // Valid
    foo.FormClosingEvent += GenericHandlerMethod;
    

    这实际上会创建 FormClosingEventHandler 的实例,而不是 EventHandler .

    但是,您无法直接订阅EventHandler类型的现有委托:

    EventHandler genericHandler = GenericHandlerMethod;
    // Invalid
    foo.FormClosingEvent += genericHandler;
    

    ...但是如果类型兼容,您可以基于现有委托创建新委托:

    EventHandler generic = GenericHandlerMethod;
    FormClosingEventHandler closingHandler = new FormClosingEventHandler(generic);
    // Valid
    foo.FormClosingEvent += closingHandler;
    

    基本上你需要记住所有语法糖都有效地调用这样的方法:

    foo.AddFormClosingHandler(handler);
    

    方法具有以下特征的签名:

    public void AddFormClosingHandler(FormClosingHandler handler)
    

    现在请记住,虽然它们具有兼容的签名,但是从 EventHandlerFormClosingHandler 没有可用的参考转换 . 它不像一个人从另一个继承 .

    通用协方差/逆变会让它变得更加混乱,但我们暂时将它留在那里......希望能给你一些可以咀嚼的东西以及围绕这些限制的选择 .

  • 1

    直接指向对象方法的委托包含三条信息:

    • 方法应该作用的目标对象,或者静态方法的情况下为“null”

    • 对作用于该类型对象的函数的引用,或者如果目标为“null”则为静态函数 .

    • 委托本身的类型 .

    通过使用 Delegate.Combine 组合总共N个单播代表生成的委托将包含N个目标,N个方法和一个委托类型 . 鉴于使用 Delegate.CombineDelegate.Remove 的(IMHO相当icky和不幸)方式,系统无法允许 Combine 的现有用途接受不同类型的委托 .

    例如,例程可能需要 EventHandler<IFoo> . 如果类 MoeLarry 都实现 IFooIBar ,则此例程应该能够接受 EventHandler<Moe>EventHandler<Larry> . 如果每个委托类型都有自己的 Combine 定义,则可以为 EventHandler<IFoo>.Combine() 提供 EventHandler<Moe> 类型的委托和 EventHandler<Larry> 之一,并让它生成 EventHandler<IFoo> 类型的组合委托处理程序 . 不幸的是,对于所有委托类型都有一个 Delegate.Combine() 方法,并且它无法查看 EventHandler<Moe>EventHandler<Larry> 并找出组合委托应该是什么类型(即使 Delegate.Combine 能够识别两个事件处理程序的类型)可以投,它无法知道是否使用 EventHandler<IFoo>EventHandler<IBar> ) .

相关问题