web-dev-qa-db-fra.com

Constructeur de base en C # - Qui est appelé en premier?

Lequel est appelé en premier - le constructeur de base ou "d'autres trucs ici"?

public class MyExceptionClass : Exception
{
    public MyExceptionClass(string message, string extrainfo) : base(message)
    {
        //other stuff here
    }
}
115
Mike Comstock

Le constructeur de base sera appelé en premier.

essayez-le:

public class MyBase
{
  public MyBase()
  {
    Console.WriteLine("MyBase");
  }
}

public class MyDerived : MyBase
{
  public MyDerived():base()
  {
    Console.WriteLine("MyDerived");
  }
}
106
craigb

Les constructeurs de classe de base sont appelés avant les constructeurs de classe dérivés, mais les initialiseurs de classe dérivée sont appelés avant les initialiseurs de classe de base. Par exemple. dans le code suivant:

public class BaseClass {

    private string sentenceOne = null;  // A

    public BaseClass() {
        sentenceOne = "The quick brown fox";  // B
    }
}

public class SubClass : BaseClass {

    private string sentenceTwo = null; // C

    public SubClass() {
        sentenceTwo = "jumps over the lazy dog"; // D
    }
}

L'ordre d'exécution est: C, A, B, D.

Consultez ces 2 articles msdn:

142
Sam Meldrum

N'essayez pas de vous en souvenir, essayez de vous expliquer ce qui doit arriver. Imaginez que vous ayez une classe de base nommée Animal et une classe dérivée nommée Dog. La classe dérivée ajoute des fonctionnalités à la classe de base. Par conséquent, lorsque le constructeur de la classe dérivée est exécuté, l'instance de classe de base doit être disponible (afin que vous puissiez y ajouter de nouvelles fonctionnalités). C'est pourquoi les constructeurs sont exécutés de la base vers les dérivés, mais les destructeurs sont exécutés de la manière opposée - d'abord les destructeurs dérivés puis les destructeurs de base.

(C'est simplifié, mais cela devrait vous aider à répondre à cette question à l'avenir sans avoir besoin de le mémoriser.)

34
David Pokluda

En fait, le constructeur de classe dérivée est exécuté en premier, mais le compilateur C # insère un appel au constructeur de classe de base comme première instruction du constructeur dérivé.

Donc: le dérivé est exécuté en premier, mais il "ressemble" à la base qui a été exécutée en premier.

21
Paolo Tedesco

Comme d'autres l'ont dit, le constructeur de base est appelé en premier. Cependant, les constructeurs ne sont pas vraiment la première chose qui se passe.

Disons que vous avez des cours comme celui-ci:

class A {}

class B : A {}

class C : B {}

Premièrement, les initialiseurs de champ seront appelés dans l'ordre des classes les plus dérivées aux moins dérivées. Donc, les premiers initialiseurs de champ de C, puis B, puis A.

Les constructeurs seront alors appelés dans l'ordre inverse: d'abord le constructeur de A, puis B, puis C.

6
Joel B Fant

Je dirais base

EDIT voir:

http://www.c-sharpcorner.com/UploadFile/rajeshvs/ConsNDestructorsInCS11122005010300AM/ConsNDestructorsInCS.aspx

là, il est écrit:

using System;
class Base
{

public Base()
{
    Console.WriteLine("BASE 1");
}
public Base(int x)
{
    Console.WriteLine("BASE 2");
}
}

class Derived : Base
{
public Derived():base(10)
{
    Console.WriteLine("DERIVED CLASS");
}
}

class MyClient
{
public static void Main()
{
    Derived d1 = new Derived();
}
}

Ce programme produit

BASE2

CLASSE DÉRIVÉE

4
Mastermind

Eric Lippert a publié un article intéressant sur la question connexe de l'initialisation d'objet, qui explique la raison de l'ordre des constructeurs et des initialiseurs de champ:

Pourquoi les initialiseurs fonctionnent-ils dans l'ordre opposé en tant que constructeurs? Première partie
Pourquoi les initialiseurs fonctionnent-ils dans l'ordre opposé en tant que constructeurs? Deuxième partie

2
Emperor XLII

Le constructeur de base est appelé en premier. Mais l'initialiseur des champs de la classe dérivée est appelé en premier.

L'ordre d'appel est

  1. initialiseur de champ de classe dérivée
  2. initialiseur de champ de classe de base
  3. constructeur de classe de base
  4. constructeur de classe dérivée

(Vous pouvez traiter 2 et 3 dans leur ensemble pour construire la classe de base.)

Tiré de CSharp Language Speification 5.0 :

10.11.3 Exécution du constructeur

Les initialiseurs de variables sont transformés en instructions d'affectation, et ces instructions d'affectation sont exécutées avant l'appel du constructeur d'instance de classe de base. Cet ordre garantit que tous les champs d'instance sont initialisés par leurs initialiseurs de variable avant l'exécution de toute instruction ayant accès à cette instance. Étant donné l'exemple

using System;
class A
{
    public A() {
        PrintFields();
    }
    public virtual void PrintFields() {}
}
class B: A
{
    int x = 1;
    int y;
    public B() {
        y = -1;
    }
    public override void PrintFields() {
        Console.WriteLine("x = {0}, y = {1}", x, y);
    }
}

lorsque new B() est utilisé pour créer une instance de B, la sortie suivante est produite:

x = 1, y = 0

La valeur de x est 1 car l'initialiseur de variable est exécuté avant l'appel du constructeur d'instance de classe de base. Cependant, la valeur de y est 0 (la valeur par défaut d'un int) car l'affectation à y n'est exécutée qu'après le retour du constructeur de la classe de base. Il est utile de considérer les initialiseurs de variable d'instance et les initialiseurs de constructeur comme des instructions qui sont automatiquement insérées avant le corps du constructeur. L'exemple

using System;
using System.Collections;
class A
{
    int x = 1, y = -1, count;
    public A() {
        count = 0;
    }
    public A(int n) {
        count = n;
    }
}
class B: A
{
    double sqrt2 = Math.Sqrt(2.0);
    ArrayList items = new ArrayList(100);
    int max;
    public B(): this(100) {
        items.Add("default");
    }
    public B(int n): base(n – 1) {
        max = n;
    }
}

contient plusieurs initialiseurs variables; il contient également des initialiseurs de constructeur des deux formes (base et ceci). L'exemple correspond au code ci-dessous, où chaque commentaire indique une instruction insérée automatiquement (la syntaxe utilisée pour les appels de constructeur insérés automatiquement n'est pas valide, mais sert simplement à illustrer le mécanisme).

using System.Collections;
class A
{
    int x, y, count;
    public A() {
        x = 1;                                // Variable initializer
        y = -1;                               // Variable initializer
        object();                         // Invoke object() constructor
        count = 0;
    }
    public A(int n) {
        x = 1;                                // Variable initializer
        y = -1;                               // Variable initializer
        object();                         // Invoke object() constructor
        count = n;
    }
}
class B: A
{
    double sqrt2;
    ArrayList items;
    int max;
    public B(): this(100) {
        B(100);                               // Invoke B(int) constructor
        items.Add("default");
    }
    public B(int n): base(n – 1) {
        sqrt2 = Math.Sqrt(2.0);           // Variable initializer
        items = new ArrayList(100);   // Variable initializer
        A(n – 1);                         // Invoke A(int) constructor
        max = n;
    }
}
1
zwcloud

http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=777

Le constructeur de base est appelé en premier.

1
mmcdole

Le constructeur d'exception sera appelé, puis votre constructeur de classe enfant sera appelé.

Simple OO principe

Jetez un œil ici http://www.dotnet-news.com/lien.aspx?ID=35151

1
CheGueVerra

Le constructeur de base sera appelé en premier, sinon, dans les cas où vos "autres choses" doivent utiliser des variables membres initialisées par votre constructeur de base, vous obtiendrez des erreurs de temps de compilation car vos membres de classe n'auront pas encore été initialisés.

0
kafuchau

base (?) est appelée avant tout travail dans le constructeur enfant.

Cela est vrai, même si vous laissez le: base () (auquel cas, le constructeur de base à 0 paramètre est appelé.)

Cela fonctionne comme Java,

public Child()
{
   super(); // this line is always the first line in a child constructor even if you don't put it there! ***
}

*** Exception: je pourrais mettre en super (1,2,3) à la place. Mais si je n'appelle pas explicitement super dans super, super () est appelé.

0
Chris Cudmore

Les appels de constructeur sont appelés (tirés) de bas en haut et exécutés de haut en bas. Ainsi, si vous aviez la classe C qui hérite de la classe B qui hérite de la classe A, lorsque vous créez une instance de classe C, le constructeur de C est appelé, qui à son tour appelle l'instructeur de B, qui à son tour appelle le constructeur de A. Maintenant, le constructeur pour A est exécuté, puis le constructeur pour B est exécuté, puis le constructeur pour C est exécuté.

0
edirtyfour