web-dev-qa-db-fra.com

C # Appelez le constructeur de la classe de base après son propre constructeur?

Comment puis-je appeler le constructeur de la classe de base après J'ai appelé mon propre constructeur?

Le problème est que le constructeur de la classe de base appelle une méthode abstraite (remplacée dans la sous-classe), qui doit accéder à la variable x, initialisée dans le constructeur de la sous-classe?

Exemple de code court:

abstract class BaseClass
{
    protected string my_string;

    protected abstract void DoStuff();

    public BaseClass()
    {
        this.DoStuff();
    }
}

class SubClass : BaseClass
{
    private TextBox tb;

    public SubClass()
        : base()
    {
        this.my_string = "Short sentence.";
    }

    protected override void DoStuff()
    {
        // This gets called from base class' constructor
        // before sub class' constructor inits my_string
        tb.Text = this.my_string;
    }
}

Edit: Sur la base des réponses, ce n'est évidemment pas possible. Existe-t-il un moyen automatisé d'appeler this.DoStuff(); sur chaque objet de SubClass une fois qu'il a été créé? Bien sûr, je pourrais simplement ajouter this.DoStuff(); après toutes les autres lignes du constructeur de la sous-classe, mais ayant environ 100 de ces classes, cela semble stupide. Une autre solution, ou devrais-je utiliser la solution manuelle?

19
user1632861

Tu ne peux pas.

De plus, vous ne devriez généralement pas appeler les méthodes virtual dans un constructeur. Voir ceci réponse .


En fonction de votre code réel et non de l'exemple simple que vous avez écrit, vous pouvez transmettre des valeurs en tant que paramètres du constructeur de base et de la méthode DoStuff. Par exemple:

abstract class BaseClass
{
    private string my_string;

    protected abstract void DoStuff(string myString);

    public BaseClass(string myString)
    {
        this.my_string = myString;
        this.DoStuff(this.my_string);
    }
}

class SubClass : BaseClass
{
    private TextBox tb;

    public SubClass()
        : base("Short sentence.")
    {
    }

    protected override void DoStuff(string myString)
    {
        tb.Text = myString;
    }
}

Si ce n'est pas possible avec votre code actuel, l'écriture de plusieurs DoStuff() fera l'affaire. N'oubliez pas non plus de sceller votre classe SubClass afin que personne d'autre ne puisse introduire de bogues en modifiant la méthode DoStuff une autre fois.

25
ken2k

Je n'appellerais pas une méthode abstraite dans le constructeur car il peut arriver que le constructeur de l'instance qui invoque la méthode ne soit pas exécuté

Lorsqu'une méthode virtuelle est appelée, le type réel qui exécute la méthode n'est sélectionné qu'au moment de l'exécution. Lorsqu'un constructeur appelle une méthode virtuelle, il est possible que le constructeur de l'instance qui appelle la méthode ne se soit pas exécuté. Pour corriger une violation de cette règle, n'appelez pas les méthodes virtuelles d'un type à partir des constructeurs du type.

http://msdn.Microsoft.com/en-us/library/ms182331%28v=vs.80%29.aspx

4
Massimiliano Peluso

Y a-t-il une raison pour laquelle vous ne pouvez pas construire une classe avant que son constructeur ne s'exécute réellement? Cela nécessite un plus grand niveau de responsabilité sur la façon dont la classe dérivée est créée et probablement pas une meilleure pratique, mais cela semble fonctionner.

abstract class BaseClass {
    protected string my_string;

    protected abstract void DoStuff();

    public BaseClass() {
        this.DoStuff();
    }
}

class SubClass: BaseClass {
    TextBox tb;

    bool Constructed = false;
    void Constructor() {
        if (!Constructed) {
            Constructed = true;
            this.my_string = "Short sentence.";
        }
    }
    public SubClass()
        : base() {
        Constructor();
    }

    protected override void DoStuff() {
        Constructor();
        // This gets called from base class' constructor
        // before sub class' constructor inits my_string
        tb.Text = this.my_string;
    }
}
0
Darin