简体   繁体   English

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

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

I have a base class DockedToolWindow : Form, and many classes that derive from DockedToolWindow. 我有一个基类DockedToolWindow:Form,还有许多从DockedToolWindow派生的类。 I have a container class that holds and assigns events to DockedToolWindow objects, however I want to invoke the events from the child class. 我有一个容器类,用于保存事件并将事件分配给DockedToolWindow对象,但是我想从子类中调用事件。

I actually have a question about how to implement what this MSDN site is telling me to do. 实际上,我对如何实现此MSDN网站告诉我的事情有疑问。 This section below is giving me the problem: 下面的这一节给了我这个问题:

    // 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);
        }
    }

Sure this example compiles and works, but when I replace "ShapeChanged" with "Move" (an event I acquired from deriving from Form), it errors saying I cannot have Move on the right side without += or -=. 当然,此示例可以编译并运行,但是当我将“ ShapeChanged”替换为“ Move”(从Form派生而来的事件)时,错误地提示我不能在没有+ =或-=的情况下在右侧移动。 I also removed the ShapeEventArgs generic tags. 我还删除了ShapeEventArgs通用标签。

Any incite on why this isn't working? 有人煽动为什么这行不通吗? What's the difference between an event declared within the class and one that is inherited? 类中声明的事件与继承的事件之间有什么区别?

You cannot directly fire base class events. 您不能直接触发基类事件。 This is exactly the reason why you had to make your OnShapeChanged method protected instead of private . 这就是为什么必须将OnShapeChanged方法protectedprivate方法的原因。

Use base.OnMove() instead. 使用base.OnMove()代替。

From the C# language spec, section 10.7 (emphasis added): 从C#语言规范的10.7节(添加了重点):

Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields . 在包含事件声明的类或结构的程序文本中,某些事件可以像fields一样使用 To be used in this way, an event must not be abstract or extern, and must not explicitly include event-accessor-declarations. 要以这种方式使用,事件不得为抽象事件或外部事件,并且不得明确包含event-accessor-declaration。 Such an event can be used in any context that permits a field. 这样的事件可以在允许字段的任何上下文中使用。 The field contains a delegate (§15) which refers to the list of event handlers that have been added to the event. 该字段包含一个委托(§15),该委托引用已添加到事件的事件处理程序的列表。 If no event handlers have been added, the field contains null. 如果未添加事件处理程序,则该字段包含null。

Thus, the reason you can't treat the Move event like a field is that it is defined in a different type (in this case, your superclass). 因此,您不能将Move事件视为一个字段,原因是它以不同的类型(在本例中为您的超类)定义。 I agree with @womp's speculation that the designers made this choice to prevent unintended monkeying with the event. 我同意@womp的推测,即设计师做出此选择是为了防止意外出现在活动中。 It seems obviously bad to allow unrelated types (types not derived from the type declaring the event) to do this, but even for derived types, it might not be desirable. 允许无关的类型(不是从声明事件的类型派生的类型)执行此操作显然很糟糕,但是即使对于派生类型,也可能不希望这样做。 They probably would have had to include syntax to allow the event declaration to be made private or protected with respect to field-style usage, so my guess is that they opted to just disallow it entirely. 他们可能必须包含语法,以允许将事件声明设为privateprotected字段样式使用的保护,因此我的猜测是他们选择完全禁止这样做。

The difference is scope. 区别在于范围。 Inside your class, you can control how your event delegates are handled, however, your class cannot control what the base class is doing. 在您的类内部,您可以控制事件委托的处理方式,但是,您的类无法控制基类的工作。 It might be doing some crazy behind-the-scenes stuff with the event and its handlers. 它可能会对事件及其处理程序进行一些疯狂的幕后操作。 If you simply "reassigned" the Move event, you would be wiping out the multicast delegate list for the event. 如果您只是“重新分配”了Move事件,则将清除该事件的多播委托列表。

I'm guessing they put a compiler restriction on this because its a very unsafe practice, and would essentially give any descendant class the ability to destroy the event model of its parent. 我猜想他们对此施加了编译器限制,因为这是一种非常不安全的做法,并且实际上将使任何后代类都有能力破坏其父级的事件模型。

You only need the code you posted in the class where the event itself is defined. 您只需要在定义事件本身的类中发布的代码。 All derived classes should simply call OnShapeChanged() or OnMove() directly, without the copying etc., so you shouldn't be writing that code at all in your classes (since the Move event is defined in the base). 所有派生类都应直接调用OnShapeChanged()或OnMove(),而不进行复制等操作,因此,您根本不应在类中编写该代码(因为Move事件是在基类中定义的)。

If you do need to do some kind of processing in the derived class (maybe you need to fiddle with your collection class?), you override the virtual OnXXX call and do you stuff before calling base.OnXXX(). 如果确实需要在派生类中进行某种处理(也许您需要弄弄集合类?),则可以覆盖虚拟的OnXXX调用,并在调用base.OnXXX()之前进行填充。 In the MSDN article, the Circle class corresponds to your DockedToolWindow class. 在MSDN文章中,Circle类对应于您的DockedToolWindow类。 The same pattern should be available to your derived classes. 您的派生类应该可以使用相同的模式。

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

相关问题 为什么事件不能在派生类中以与C#中的基类相同的方式使用? - Why events can't be used in the same way in derived classes as in the base class in C#? 基类和派生类的C#事件处理问题 - C# Events handling problem for base and derived classes 派生类应该处理基类的事件吗? (C#/ WPF) - Should a derived class handle the events of a base class? (C# / WPF) C#-需要基类上的接口,但仅派生类中的实现 - C# - require an interface on a base class but only the implementations in derived classes C# 仅在选定的派生类中使用基类方法 - C# use base class methods in selected derived classes only 一个派生类的多个基类,在C#中继承 - Multiple base classes for one derived class, inheritance in C# 将派生类的方法重构为公共基类的方法? (C#) - Refactoring Derived Classes' Methods to Common Base Class' Method? (C#) C# - 让所有派生类都调用基类构造函数 - C# - Making all derived classes call the base class constructor C#:定义基类中的方法实现和派生类中的属性 - C#: Define methods implementation in base class and properties in derived classes 在 C# 中的基类中使用泛型:如何确保基类中的方法返回派生类的类型? - Using Generics in Base Classes in C#: How to ensure methods in the base class return the derived class's type?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM