我有一个基类 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);
        }
    }

当然,这个例子可以编译并工作,但是当我用“Move”(我从 Form 派生获得的一个事件)替换“ShapeChanged”时,它错误地说我不能在没有 += 或 -= 的情况下将 Move 放在右侧。我还删除了 ShapeEventArgs 通用标签。

任何煽动为什么这不起作用?在类中声明的事件和继承的事件之间有什么区别?

有帮助吗?

解决方案

您不能直接解雇基类事件。这正是您必须制作您的 OnShapeChanged 方法 protected 代替 private.

利用 base.onmove() 反而。

其他提示

根据C#语言规范第10.7节(添加了强调):

在包含事件声明的类或结构的程序文本中,可以像字段一样使用某些事件. 。要以这种方式使用,事件不得是抽象或外部,并且不得明确包含事件访问者 - 销售。这样的事件可以在任何允许字段的上下文中使用。该字段包含一个代表(§15),该代表指的是已添加到活动的事件处理程序列表。如果没有添加事件处理程序,则该字段包含空。

因此,您无法将移动事件视为字段的原因是它以其他类型定义(在这种情况下为您的超类)。我同意 @WOMP的猜测,即设计师做出了选择,以防止事件发生意想不到的猴子。允许允许无关类型(不是从声明事件的类型派生的类型)来执行此操作似乎很不好,但是即使对于派生类型,也可能是不可取的。他们可能不得不包括语法以允许发表事件声明 private 或者 protected 关于现场风格的使用,所以我的猜测是他们选择完全禁止它。

区别在于范围。在您的班级内部,您可以控制事件代表的处理方式,但是,您的班级无法控制基类在做什么。它可能会在活动及其处理程序中做一些疯狂的幕后工作。如果您简单地“重新分配”了移动事件,您将删除该事件的多播代表列表。

我猜他们对此对编译器进行了限制,因为它是一种非常不安全的练习,从本质上讲,任何后代类都可以破坏其父母的事件模型。

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top