Question Ordre de chaînage du constructeur


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

public frmConfirm(): this(1)

quand le constructeur surchargé est-il appelé? En outre, quelqu'un peut-il confirmer que si la classe est un formulaire, l'appel InitializeComponent () dans les deux constructeurs posera des problèmes?


32
2018-01-05 22:16


origine


Réponses:


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

Donc, si vous enchaînez avec 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;
    }
}

Ceci est le 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.


43
2018-01-05 22:18



le this(1) le constructeur est appelé en premier.

En ce qui concerne votre deuxième question, à cause 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.


9
2018-01-05 22:19



L'endroit pour chercher des réponses sur une question comme celle-ci est la Spécification du langage C #. Dans la section 10.11.1, initialiseurs de constructeur vous pouvez lire (l'emphase est la mienne):

Tous les constructeurs d'instance (sauf   ceux pour objet de classe) implicitement   inclure une invocation d'un autre   constructeur d'instance immédiatement   avant le constructeur-corps.

Des lectures supplémentaires montrent que:

  • si le constructeur a un initialiseur de constructeur d'instance du formulaire base(arguments), un constructeur de la classe de base directe sera invoqué.
  • si le constructeur a un initialiseur de constructeur d'instance du formulaire this(argument), un constructeur de la classe sera invoqué.
  • si aucun initialiseur de constructeur d'instance n'est fourni, base() sera ajouté automatiquement.

5
2018-01-05 22:34