2009-03-09 8 views
13

J'ai la hiérarchie suivante:appel constructeur de base en C#

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 

    string sMessage = "Blah " + someParams; 

    //Here I want to call the base constructor 
    //base(sMessage); 

    } 

} 

Répondre

16

Vous devez appeler le constructeur de la classe de base avant le corps du constructeur de la classe dérivée.

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 

    } 

} 
+0

C'est probablement la meilleure solution pour ce cas simple, mais elle deviendrait vite moche si la construction du paramètre était beaucoup plus complexe. – tvanfosson

+0

Cela est vrai, bien que vous puissiez également construire le paramètre dans une méthode statique et transmettre le résultat au constructeur de la classe de base. Je préfère ça à l'approche du crochet. Ou, comme il s'agit de .NET, vous pouvez supprimer les éléments du constructeur et le faire dans les setters, ce qui est favorable à la sérialisation. – OregonGhost

7

Vous ne pouvez pas. Vous pouvez l'appeler avant:

public Derived() : base() 

ou vous devez utiliser un crochet

class Base 
{ 
    protected void init() { } 
    public Base(string sMessage) 
    { 
    init(); 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 
    string sMessage = "Blah " + someParams; 
    init(); 
    } 
} 
+0

Étant donné que le constructeur de base est supposé faire des choses (supposé possible avec sMessage), comment ce code résout-il son problème? – wcm

+0

Si vous utilisez le hook, vous devez éviter d'appeler le constructeur de base par défaut. Voir ma réponse pour un moyen d'éviter cela en fournissant un constructeur qui n'exécute pas l'initialiseur. – tvanfosson

+0

@wcm: Je montre juste les étapes pour réaliser l'ordre des opérations dont DotnetDude a besoin. On dirait qu'il comprend C# assez bien pour modifier les paramètres et retourner l'objet pour qu'il corresponde à ses besoins réels d'ici. – Dinah

0
public Derived(string someParams) : base(someParams) 
{ 
    string sMessage = "Blah " + someParams; 
} 

Ceci est la façon dont vous devez le faire. Vous pourriez peut-être mettre le code que vous voulez appeler ensuite dans une méthode protégée dans la classe de base et vous pouvez l'appeler par la suite comme ceci:

class Base 
{ 
    public Base(string sMessage) 
    { 
    ConstructorStuff(); 
    } 

    protected Base() 
    { 
    } 

    protected void ConstructorStuff() 
    { 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    {  
    string sMessage = "Blah " + someParams; 

    ConstructorStuff();  
    }  
} 
+1

Cela lancera deux fois ConstructorStuff - une fois lorsque le constructeur de base par défaut est appelé avant le constructeur dérivé et une fois pendant l'exécution du constructeur dérivé. – tvanfosson

+0

Erm? Base n'a pas un constructeur par défaut qui appelle ConstructorStuff? –

+1

Ah.Ensuite, vous devez fournir un constructeur par défaut sinon le code ne compilera pas puisque votre classe dérivée en aura besoin. Le problème reste que le constructeur par défaut devra également utiliser ConstructorStuff et vous avez besoin d'un autre qui n'invoque pas l'initialiseur. – tvanfosson

1

Points à noter sur les constructeurs:

· Constructors ne peut pas être "virtuel".

· Ils ne peuvent pas être hérités.

· Les constructeurs sont appelés dans l'ordre de l'héritage.

public Child(string a):base(a){} 
4

Si vous avez vraiment besoin d'avoir votre course constructeur d'abord, je suggère d'utiliser une méthode Initialize protégée qui est invoquée par vos constructeurs et fait le travail réel d'initialisation de la classe. Vous devez fournir un autre constructeur qui permettra d'ignorer l'initialisation.

public class Base 
{ 

    public Base() : this(true) { } 

    protected Base(bool runInitializer) 
    { 
     if (runInitializer) 
     { 
      this.Initialize(); 
     } 
    } 

    protected void Initialize() 
    { 
     ...initialize... 
    } 
} 

public class Derived : Base 
{ 
    // explicitly referencing the base constructor keeps 
    // the default one from being invoked. 
    public Derived() : base(false) 
    { 
     ...derived code 
     this.Initialize(); 
    } 
} 
0

En fait, la solution la plus simple est:

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 
    } 

} 

Pourquoi le rendre plus compliqué?

+0

Ouais, j'ai remarqué après que OregonGhost a déjà suggéré cela .. –

6

Au départ, je raté le commentaire de OregonGhost sur l'utilisation d'une méthode statique pour modifier le paramètre qui est avéré pour moi, le plus utile si je pensais que je rajouterais un exemple de code pour les autres qui ont lu cette discussion:

class Base 
{ 
    public Base(string sMessage) 
    { 
     // Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string sMessage) : base(AdjustParams(sMessage)) 
    { 
    } 

    static string AdjustParams(string sMessage) 
    { 
     return "Blah " + sMessage; 
    } 
} 
Questions connexes