27 Stimmen

Sicherstellen, dass die Basismethode in C# aufgerufen wird

Kann ich eine abgeleitete Klasse irgendwie dazu zwingen, immer die überschriebenen Basismethoden aufzurufen?

public class BaseClass
{
    public virtual void Update()
    {
        if(condition)
        {
            throw new Exception("..."); // Prevent derived method to be called
        }
    }
}

Und dann in einer abgeleiteten Klasse :

public override void Update()
{
    base.Update(); // Forced call

    // Do any work
}

Ich habe gesucht und einen Vorschlag gefunden, ein nicht-virtuelles Update() zu verwenden, aber auch ein geschütztes virtuelles UpdateEx(). Es fühlt sich einfach nicht sehr ordentlich, gibt es keinen besseren Weg?

Ich hoffe, Sie verstehen die Frage und entschuldige mich für mein schlechtes Englisch.

33voto

Jon Skeet Punkte 1325502

Verwenden Sie die Vorlage Methode Muster - Überschreiben Sie nicht die Basismethode, die etwas tun muss, sondern ein bestimmtes Bit, das entweder abstrakt oder ein No-op in der Basisklasse sein kann. (Die Entscheidung, ob es ein No-op oder abstrakt sein soll, ist in der Regel ziemlich offensichtlich - macht die Basisklasse als konkrete Klasse für sich genommen Sinn?)

Es klingt so, als wäre dies das Muster, das Sie bei UpdateEx - obwohl es normalerweise UpdateImpl oder meiner Erfahrung nach etwas Ähnliches. Meiner Meinung nach ist an diesem Muster nichts auszusetzen - es vermeidet die Idee, alle abgeleiteten Klassen zu zwingen, denselben Code zu schreiben, um die Basismethode aufzurufen.

7voto

ShawnFeatherly Punkte 1990

Ich habe ein bisschen gebraucht, um zu verstehen, wie Update und UpdateEx aussehen würden. Hier ist ein Codebeispiel, das anderen helfen könnte.

public class BaseClass
{
    // This is the Update that class instances will use, it's never overridden by a subclass
    public void Update()
    {
        if(condition);
        // etc... base class code that will always run

        UpdateEx(); // ensure subclass Update() functionality is run
    }

    protected virtual void UpdateEx()
    {
        // does nothing unless sub-class overrides
    }
}

Eine Unterklasse wird nie eine Implementierung für Update() haben. Sie verwendet UpdateEx(), um die Implementierung von Update() hinzuzufügen;

public class ConcreteClass : BaseClass
{
    protected override void UpdateEx()
    {
        // implementation to be added to the BaseClass Update();
    }
}

Jede Instanz von ConcreteClass wird die BaseClass-Implementierung von Update() verwenden, wie auch immer ConcreteClass sie mit UpdateEx() erweitert.

2voto

ChrisW Punkte 53239

Ich denke, dass der Vorschlag, den Sie gefunden haben, gut ist.

Die einzige Methode der Basisklasse, die Sie nicht vermeiden können, von der Unterklasse im Konstruktor der Basisklasse aufzurufen.

2voto

Daniel Pryden Punkte 56882

Ich denke, ein nicht-virtuelles Basismitglied, das einen virtuellen "Hook" aufruft, der erweitert werden kann, ist die gängigste Lösung für diese Art von Problem.

Je nach Anwendungsfall können Sie eine event statt, aber das übliche Muster für die Implementierung eines Ereignisses besteht darin, eine virtuelle OnEvent Methode, die von Unterklassen überschrieben werden kann, anstatt einen Ereignishandler hinzuzufügen, so dass es in Ihrem Beispiel auf dasselbe hinausläuft.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X