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
}
}
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");
}
}
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:
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.)
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.
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
.
Je dirais base
EDIT voir:
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
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
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
(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 deB
, 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 dey
est 0 (la valeur par défaut d'unint
) 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'exempleusing 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; } }
http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=777
Le constructeur de base est appelé en premier.
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
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.
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é.
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é.