繁体   English   中英

在派生类C#中引发基类事件

[英]Raise Base Class Events in Derived Classes C#

我有一个基类DockedToolWindow:Form,还有许多从DockedToolWindow派生的类。 我有一个容器类,用于保存事件并将事件分配给DockedToolWindow对象,但是我想从子类中调用事件。

实际上,我对如何实现此MSDN网站告诉我的事情有疑问。 下面的这一节给了我这个问题:

    // The event. Note that by using the generic EventHandler<T> event type
    // we do not need to declare a separate delegate type.
    public event EventHandler<ShapeEventArgs> ShapeChanged;

    public abstract void Draw();

    //The event-invoking method that derived classes can override.
    protected virtual void OnShapeChanged(ShapeEventArgs e)
    {
        // Make a temporary copy of the event to avoid possibility of
        // a race condition if the last subscriber unsubscribes
        // immediately after the null check and before the event is raised.
        EventHandler<ShapeEventArgs> handler = ShapeChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }

当然,此示例可以编译并运行,但是当我将“ ShapeChanged”替换为“ Move”(从Form派生而来的事件)时,错误地提示我不能在没有+ =或-=的情况下在右侧移动。 我还删除了ShapeEventArgs通用标签。

有人煽动为什么这行不通吗? 类中声明的事件与继承的事件之间有什么区别?

您不能直接触发基类事件。 这就是为什么必须将OnShapeChanged方法protectedprivate方法的原因。

使用base.OnMove()代替。

从C#语言规范的10.7节(添加了重点):

在包含事件声明的类或结构的程序文本中,某些事件可以像fields一样使用 要以这种方式使用,事件不得为抽象事件或外部事件,并且不得明确包含event-accessor-declaration。 这样的事件可以在允许字段的任何上下文中使用。 该字段包含一个委托(§15),该委托引用已添加到事件的事件处理程序的列表。 如果未添加事件处理程序,则该字段包含null。

因此,您不能将Move事件视为一个字段,原因是它以不同的类型(在本例中为您的超类)定义。 我同意@womp的推测,即设计师做出此选择是为了防止意外出现在活动中。 允许无关的类型(不是从声明事件的类型派生的类型)执行此操作显然很糟糕,但是即使对于派生类型,也可能不希望这样做。 他们可能必须包含语法,以允许将事件声明设为privateprotected字段样式使用的保护,因此我的猜测是他们选择完全禁止这样做。

区别在于范围。 在您的类内部,您可以控制事件委托的处理方式,但是,您的类无法控制基类的工作。 它可能会对事件及其处理程序进行一些疯狂的幕后操作。 如果您只是“重新分配”了Move事件,则将清除该事件的多播委托列表。

我猜想他们对此施加了编译器限制,因为这是一种非常不安全的做法,并且实际上将使任何后代类都有能力破坏其父级的事件模型。

您只需要在定义事件本身的类中发布的代码。 所有派生类都应直接调用OnShapeChanged()或OnMove(),而不进行复制等操作,因此,您根本不应在类中编写该代码(因为Move事件是在基类中定义的)。

如果确实需要在派生类中进行某种处理(也许您需要弄弄集合类?),则可以覆盖虚拟的OnXXX调用,并在调用base.OnXXX()之前进行填充。 在MSDN文章中,Circle类对应于您的DockedToolWindow类。 您的派生类应该可以使用相同的模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM