为什么虚拟事件不调用重写的处理程序

本文关键字:处理 程序 重写 调用 虚拟 事件 为什么 | 更新日期: 2023-09-27 18:03:51

考虑下面的场景,可能这个场景是非常假设的

public delegate void MyDel();
public class T1
{
    public T1()
    {
    }
    public virtual event MyDel MyEvent;
    public virtual void RaiseEvent()
    {
        MyEvent();
     }
    protected virtual void HandleEvent()
    {
        MessageBox.Show("base event");
    }
}
public class T2:T1
{
    public override event MyDel MyEvent;
    public T2()
    {
        MyEvent += new MyDel(HandleEvent);
    }
    protected override void HandleEvent()
    {
        MessageBox.Show("overridden event");
    }
}

和主客户端代码

        baseT = new T2();
        baseT.MyEvent += new MyDel(() => MessageBox.Show("From client"));
        baseT.RaiseEvent(); 

为什么会抛出异常,为什么虚拟事件的行为不像虚拟/重写的方法?

为什么虚拟事件不调用重写的处理程序

事件的接口实际上只是一对方法,add和remove。为自动实现的事件生成私有支持委托,该委托只能在声明类中通过事件名称访问。

事件的virtual关键字只适用于add/remove方法对。对于自动实现的事件,访问和调用支持委托不是虚拟的。当订阅发生在派生类(T2)的实例上时,它使用重写的add/remove方法,这些方法使用它自己的支持委托。基类的支持委托仍然为空,并且仍然在RaiseEvent中被调用。当调用RaiseEvent时,会产生一个NullReferenceException

虚拟事件是很少见的。我可能会将事件本身设置为非虚拟的,并使用受保护的虚拟方法来允许派生类修改事件的行为。