J’ai besoin d’appeler un constructeur du corps d’un autre. Comment puis je faire ça?
Fondamentalement
class foo { public foo (int x, int y) { } public foo (ssortingng s) { // ... do something // Call another constructor this (x, y); // Doesn't work foo (x, y); // neither } }
Tu ne peux pas.
Vous devrez trouver un moyen d’enchaîner les constructeurs, comme dans:
public foo (int x, int y) { } public foo (ssortingng s) : this(XFromSsortingng(s), YFromSsortingng(s)) { ... }
ou déplacez votre code de construction dans une méthode d’installation commune, comme ceci:
public foo (int x, int y) { Setup(x, y); } public foo (ssortingng s) { // do stuff int x = XFromSsortingng(s); int y = YFromSsortingng(s); Setup(x, y); } public void Setup(int x, int y) { ... }
this(x, y)
est correct, mais il doit l’être avant le début du corps du constructeur:
public Foo(int x, int y) { ... } public Foo(ssortingng s) : this(5, 10) { }
Notez que:
this
ci, soit la base
– ce constructeur peut chaîner un autre, bien sûr. this
dans les arguments de l’autre constructeur, y compris en appelant des méthodes d’instance, mais vous pouvez appeler des méthodes statiques. J’ai un peu plus d’informations dans mon article sur l’enchaînement des constructeurs .
Pour appeler explicitement les constructeurs de base et de classe, vous devez utiliser la syntaxe donnée ci-dessous (notez que vous ne pouvez pas l’utiliser en C # pour initialiser des champs comme en C ++):
class foo { public foo (int x, int y) { } public foo (ssortingng s) : this(5, 6) { // ... do something } }
// EDIT: Notez que vous avez utilisé x, y dans votre échantillon. Bien sûr, les valeurs données lors de l’appel de ctor de cette manière ne peuvent pas s’appuyer sur les parameters d’un autre constructeur, elles doivent être résolues d’une autre manière (elles n’ont pas besoin d’être des constantes bien que dans l’exemple de code édité ci-dessus). Si x
et y
sont calculés à partir de s
, vous pouvez le faire comme suit:
public foo (ssortingng s): this (GetX (s), GetY (s))
Ceci n’est pas supporté – voir Constructeurs en C # .
Cependant, vous pouvez implémenter une méthode commune (privée) que vous appelez à partir des différents constructeurs …
J’ai rencontré ce problème une ou deux fois moi-même … J’ai fini par extraire la logique dont j’avais besoin dans cet autre constructeur en une méthode de private void
et en l’appelant à ces deux endroits.
class foo { private void Initialize(int x, int y) { //... do stuff } public foo(int x, int y) { Initialize(x, y); } public foo(ssortingng s_ { // ... do stuff Initialize(x, y) // ... more stuff } }
Il y a une note dans la description de MethodBase.Invoke
dans MSDN
Si cette surcharge de méthode est utilisée pour appeler un constructeur d’instance, l’object fourni pour obj est réinitialisé. c’est-à-dire que tous les initialiseurs d’instance sont exécutés. La valeur de retour est null. Si un constructeur de classe est appelé, la classe est réinitialisée. c’est-à-dire que tous les initialiseurs de classe sont exécutés. La valeur de retour est null.
Vous pouvez obtenir la méthode du constructeur par reflection et l’appeler via Invoke
dans le corps de votre nouveau constructeur. Mais je ne l’ai pas essayé . Et, bien entendu, cette solution présente de nombreux inconvénients.