Frage

Ich habe eine Basisklasse angedockt, und viele Klassen, die aus DockedtoolWindow stammen. Ich habe eine Containerklasse, die Ereignisse hält und zuweist, an denen Objekte angedockt werden, aber ich möchte die Ereignisse aus der Kinderklasse aufrufen.

Ich habe tatsächlich eine Frage, wie ich das implementieren kann, was dies ist MSDN Site Sagt mir, dass ich es tun soll. In diesem Abschnitt unten gibt mir das 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);
        }
    }

Sicher, dieses Beispiel kompiliert und funktioniert, aber wenn ich "Shapechanged" durch "Move" ersetze (ein Ereignis, das ich von Form aus dem Formular abgeleitet habe), sagen es Fehler, dass ich ohne += oder -= keine Bewegung auf der rechten Seite haben kann. Ich habe auch die generischen Tags von ShapeEventArgs entfernt.

Irgendwelche Anreize darüber, warum das nicht funktioniert? Was ist der Unterschied zwischen einem in der Klasse deklarierten Ereignis und einem, der vererbt wird?

War es hilfreich?

Lösung

Sie können Ereignisse der Basisklassen nicht direkt abfeuern. Dies ist genau der Grund, warum Sie Ihre machen mussten OnShapeChanged Methode protected Anstatt von private.

Verwenden Base.onMove () stattdessen.

Andere Tipps

Aus der C# Language Spec, Abschnitt 10.7 (Hervorhebung hinzugefügt):

Innerhalb des Programmtextes der Klasse oder Struktur, die die Erklärung eines Ereignisses enthält, können bestimmte Ereignisse wie Felder verwendet werden. Um auf diese Weise verwendet zu werden, darf ein Ereignis nicht abstrakt oder extern sein und darf nicht explizit Ereignis-Zugriffsdeklarationen enthalten. Ein solches Ereignis kann in jedem Kontext verwendet werden, der ein Feld ermöglicht. Das Feld enthält einen Delegierten (§15), der sich auf die Liste der Ereignishandler bezieht, die dem Ereignis hinzugefügt wurden. Wenn keine Event -Handler hinzugefügt wurden, enthält das Feld NULL.

Der Grund, warum Sie das Move -Ereignis nicht wie ein Feld behandeln können, ist, dass es in einem anderen Typ definiert ist (in diesem Fall Ihre Superklasse). Ich stimme den Spekulationen von @WOMP zu, dass die Designer diese Entscheidung getroffen haben, um das unbeabsichtigte Affen für die Veranstaltung zu verhindern. Es erscheint offensichtlich schlecht, nicht verwandte Typen zuzulassen (Typen, die nicht aus dem Typ, der das Ereignis deklariert, dies tun, aber selbst für abgeleitete Typen ist es möglicherweise nicht wünschenswert. Sie hätten wahrscheinlich die Syntax einbeziehen müssen, um die Ereigniserklärung abzugeben zu lassen private oder protected In Bezug auf den Gebrauch im Feldstil ist ich also vermute, dass sie sich dafür entschieden haben, es einfach völlig zu verhindern.

Der Unterschied ist Umfang. In Ihrer Klasse können Sie steuern, wie Ihre Veranstaltungsdelegierten behandelt werden. Ihre Klasse kann jedoch nicht steuern, was die Basisklasse tut. Mit dem Ereignis und seinen Handlern könnte es ein paar verrückte Sachen hinter den Kulissen machen. Wenn Sie das Move -Ereignis einfach "neu zugewiesen" hätten, würden Sie die Multicast -Delegate -Liste für das Ereignis auslöschen.

Ich vermute, sie setzen eine Compiler -Beschränkung darauf ein, weil es eine sehr unsichere Praxis ist, und würden jeder Nachkommenklasse im Wesentlichen die Fähigkeit geben, das Ereignismodell seines Elternteils zu zerstören.

Sie benötigen nur den Code, den Sie in der Klasse gepostet haben, in der das Ereignis selbst definiert ist. Alle abgeleiteten Klassen sollten einfach OnShapeChanged () oder onMove () direkt, ohne das Kopieren usw. aufrufen, sodass Sie diesen Code überhaupt nicht in Ihren Klassen schreiben sollten (da das Move -Ereignis in der Basis definiert ist).

Wenn Sie in der abgeleiteten Klasse eine Art Verarbeitung durchführen müssen (vielleicht müssen Sie mit Ihrer Sammelklasse herumspielen?), Überschreiben Sie den virtuellen Onxxx -Anruf und füllen Sie es, bevor Sie Base.onxxx () aufrufen. Im MSDN -Artikel entspricht die Kreisklasse Ihrer DockedtoolWindow -Klasse. Das gleiche Muster sollte Ihren abgeleiteten Klassen zur Verfügung stehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top