46 votes

Ordre de chaînage des constructeurs

Si vous enchaînez les appels de constructeurs en utilisant la syntaxe :

public frmConfirm(): this(1)

Quand le constructeur surchargé est-il appelé ? De plus, quelqu'un peut-il confirmer que si la classe est un formulaire, le fait d'avoir l'appel InitializeComponent() dans les deux constructeurs posera des problèmes ?

48voto

cdhowie Points 62253

Le constructeur chaîné sera appelé immédiatement avant le corps du constructeur de définition. La séquence IL générée est un appel immédiat de call à l'autre constructeur, suivi de l'IL généré à partir des déclarations dans le constructeur.

Donc si vous enchaînez à un autre constructeur et que ce constructeur appelle InitializeComponent() le constructeur appelant ne doit pas appeler cette méthode.

Par exemple, étant donné cet exemple de classe :

class Foo {
    public int A, B;

    public Foo() : this(1) {
        B = 2;
    }

    public Foo(int a) {
        A = a;
    }
}

Il s'agit de l'IL généré :

  .class private auto ansi beforefieldinit Foo
        extends [mscorlib]System.Object
  {
    .field  public  int32 A
    .field  public  int32 B

    // method line 1
    .method public hidebysig  specialname  rtspecialname
           instance default void '.ctor' ()  cil managed
    {
        .maxstack 8
        IL_0000:  ldarg.0
        IL_0001:  ldc.i4.1
        IL_0002:  call instance void class Foo::'.ctor'(int32)
        IL_0007:  ldarg.0
        IL_0008:  ldc.i4.2
        IL_0009:  stfld int32 Foo::B
        IL_000e:  ret
    } // end of method Foo::.ctor

    // method line 2
    .method public hidebysig  specialname  rtspecialname
           instance default void '.ctor' (int32 a)  cil managed
    {
        .maxstack 8
        IL_0000:  ldarg.0
        IL_0001:  call instance void object::'.ctor'()
        IL_0006:  ldarg.0
        IL_0007:  ldarg.1
        IL_0008:  stfld int32 Foo::A
        IL_000d:  ret
    } // end of method Foo::.ctor

  } // end of class Foo

Notez que le constructeur no-arg appelle l'autre constructeur avant d'affecter 2 au champ B.

14voto

Jacob Points 33729

El this(1) est appelé en premier.

En ce qui concerne votre deuxième question, en raison de la InitializeComponent et d'autres problèmes liés à l'héritage des formulaires, je vous suggère d'utiliser la composition plutôt que l'héritage.

10voto

Fredrik Mörk Points 85694

L'endroit où chercher des réponses à une question comme celle-ci est le Spécification du langage C# . Dans la section Initialisateurs de constructeurs que vous pouvez lire (c'est moi qui souligne) :

Tous les constructeurs d'instance (sauf ceux de la classe object) incluent implicitement implicitement une invocation d'un autre constructeur d'instance immédiatement avant le corps du constructeur.

Une lecture plus approfondie montre que :

  • si le constructeur a un initialisateur de constructeur d'instance de la forme base(arguments) un constructeur de la classe de base directe sera invoqué.
  • si le constructeur a un initialisateur de constructeur d'instance de la forme this(argument) un constructeur de la classe elle-même sera invoqué.
  • si aucun initialisateur de constructeur d'instance n'est fourni, base() sera ajouté automatiquement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X