web-dev-qa-db-fra.com

Ordre d'exécution du constructeur C #

En C #, quand vous le faites

Class(Type param1, Type param2) : base(param1) 

le constructeur de la classe est-il exécuté en premier, puis le constructeur de la superclasse est appelé ou appelle-t-il d'abord le constructeur de base?

112
webdreamer

La commande est:

  • Les variables membres sont initialisées aux valeurs par défaut pour toutes les classes de la hiérarchie

Commençant ensuite par la classe la plus dérivée:

  • Les initialiseurs de variables sont exécutés pour le type le plus dérivé
  • Le chaînage de constructeur détermine quel constructeur de classe de base va être appelé
  • La classe de base est initialisée (répétez tout cela :)
  • Les corps constructeurs de la chaîne de cette classe sont exécutés (notez qu'il peut y en avoir plusieurs s'ils sont chaînés avec Foo() : this(...) etc

Notez qu'en Java, la classe de base est initialisée avant que les initialiseurs de variable soient exécutés. Si vous portez un code, c'est une différence importante à savoir :)

J'ai un page avec plus de détails si cela vous intéresse.

161
Jon Skeet

Il appellera d'abord le constructeur de base. Gardez également à l'esprit que si vous ne placez pas la :base(param1) après votre constructeur, le constructeur vide de la base sera appelé.

48
Yuriy Faktorovich

Le constructeur de la classe de base est appelé en premier.

12
tanascius

Je ne sais pas si cela devrait être un commentaire/réponse, mais pour ceux qui apprennent par l'exemple, ce violon illustre également l'ordre: https://dotnetfiddle.net/kETPKP

using System;

// order is approximately
/*
   1) most derived initializers first.
   2) most base constructors first (or top-level in constructor-stack first.)
*/
public class Program
{
    public static void Main()
    {
        var d = new D();
    }
}

public class A
{
    public readonly C ac = new C("A");

    public A()
    {
        Console.WriteLine("A");
    }
    public A(string x) : this()
    {
        Console.WriteLine("A got " + x);
    }
}

public class B : A
{
    public readonly C bc = new C("B");

    public B(): base()
    {
        Console.WriteLine("B");
    }
    public B(string x): base(x)
    {
        Console.WriteLine("B got " + x);
    }
}

public class D : B
{
    public readonly C dc = new C("D");

    public D(): this("ha")
    {
        Console.WriteLine("D");
    }
    public D(string x) : base(x)
    {
        Console.WriteLine("D got " + x);
    }
}

public class C
{
    public C(string caller)
    {
        Console.WriteLine(caller + "'s C.");
    }
}

Résultat:

D's C.
B's C.
A's C.
A
A got ha
B got ha
D got ha
D
7
user420667

[Edit: dans le temps qu'il m'a fallu pour répondre, la question avait totalement changé].

La réponse est qu'elle appelle la base en premier.

[Réponse originale à l'ancienne question ci-dessous]

Demandez-vous quand vous feriez le bit "base" de l'appel constructeur?

Si c'est le cas, vous "chaîneriez" un appel à la base du constructeur si la classe est dérivée d'une autre classe qui a ce constructeur:

  public class CollisionBase
    {
        public CollisionBase(Body body, GameObject entity)
        {

        }
    }

    public class TerrainCollision : CollisionBase
    {
        public TerrainCollision(Body body, GameObject entity)
            : base(body, entity)
        {

        }
    }

Dans cet exemple, TerrainCollision dérive de CollisionBase. En chaînant les constructeurs de cette manière, il garantit que le constructeur spécifié est appelé sur la classe de base avec les paramètres fournis, plutôt que le constructeur par défaut (s'il y en a un sur la base)

1
Rob Levine

Votre question n'est pas claire, mais je suppose que vous vouliez poser les questions suivantes

Quand dois-je appeler le constructeur de base pour mon objet XNA par rapport à l'utilisation du constructeur par défaut impilict

La réponse à cette question dépend fortement de votre scénario et de l'objet sous-jacent. Pourriez-vous clarifier un peu les points suivants

  • Quel est le scénario
  • Quel est le type de l'objet de base de TerrainCollision?

Ma meilleure réponse est cependant que dans le cas où vous avez des paramètres qui correspondent aux paramètres du constructeur de la classe de base, vous devriez presque certainement l'appeler.

0
JaredPar

Le mécanisme du constructeur est bien meilleur car il laisse l'application utiliser le chaînage du constructeur et si vous étendez l'application, il permet par héritage la possibilité de faire des changements de code minimaux. Article de Jon Skeets

0
lloydom