Что вызвано первым - базовый конструктор или "другое вещество здесь"?
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
Что вызвано первым - базовый конструктор или "другое вещество здесь"?
public class MyExceptionClass : Exception
{
public MyExceptionClass(string message, string extrainfo) : base(message)
{
//other stuff here
}
}
Сначала будет вызываться базовый конструктор.
попробуйте:
public class MyBase
{
public MyBase()
{
Console.WriteLine("MyBase");
}
}
public class MyDerived : MyBase
{
public MyDerived():base()
{
Console.WriteLine("MyDerived");
}
}
Конструкторы базового класса вызываются перед конструкторами производных классов, но инициализаторы производных классов вызывается перед инициализаторами базового класса. Например. в следующем коде:
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
}
}
Порядок выполнения: C, A, B, D.
Просмотрите эти статьи из 2 msdn:
Не пытайтесь запомнить это, попробуйте объяснить себе, что должно произойти. Представьте, что у вас есть базовый класс с именем Animal и производным классом Dog. Полученный класс добавляет некоторые функциональные возможности базовому классу. Поэтому, когда выполняется конструктор производного класса, экземпляр базового класса должен быть доступен (чтобы вы могли добавить к нему новые функции). Поэтому конструкторы выполняются из базы в производную, но деструкторы выполняются в обратном порядке - сначала производные деструкторы, а затем базовые деструкторы.
(Это упрощено, но оно должно помочь вам ответить на этот вопрос в будущем без необходимости запоминать это.)
На самом деле, конструктор производного класса выполняется первым, но компилятор С# вставляет вызов в конструктор базового класса в качестве первого оператора производного конструктора.
Итак: производный выполняется сначала, но он выглядит "сначала".
Как говорили другие, базовый конструктор сначала вызывается. Однако конструкторы на самом деле не первое, что происходит.
Скажем, у вас есть такие классы:
class A {}
class B : A {}
class C : B {}
Во-первых, инициализаторы полей будут вызываться в порядке наиболее выведенных для наименее производных классов. Итак, первые инициализаторы поля C
, затем B
, затем A
.
Затем конструкторы будут вызываться в противоположном порядке: сначала конструктор A
, затем B
, затем C
.
Я бы сказал base
ИЗМЕНИТЬ:
там говорится:
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();
}
}
Эта программа выводит
BASE2
ПОЛУЧЕННЫЙ КЛАСС
http://www.devhood.com/tutorials/tutorial_details.aspx?tutorial_id=777
Сначала создается базовый конструктор.
Вызывается Exception Constructor, тогда вызывается ваш конструктор класса Child.
Простой принцип OO
Посмотрите здесь http://www.dotnet-news.com/lien.aspx?ID=35151
У Эрика Липперта был интересный пост по связанной проблеме инициализации объекта, который объясняет причину упорядочения конструкторов и инициализаторов полей:
Почему инициализаторы работают в противоположном порядке как конструкторы? Часть первая
Почему инициализаторы работают в противоположном порядке как конструкторы? Часть вторая
Основной конструктор называется первым. Но инициализатор полей в производном классе вызывается первым.
Вызывающий порядок
(Вы можете обрабатывать 2 и 3 в целом для создания базового класса.)
Взято из CSharp Language Speification 5.0:
10.11.3 Выполнение конструктора
Переменные инициализаторы преобразуются в операторы присваивания, и эти присвоения операторы выполняются перед вызовом базового класса конструктор экземпляра. Это упорядочение гарантирует, что все поля экземпляра инициализируются их переменными инициализаторами перед любыми утверждениями которые имеют доступ к этому экземпляру. Учитывая пример
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); } }
когда
new B()
используется для создания экземпляраB
, следующее вывод:x = 1, y = 0
Значение
x
равно 1, поскольку выполняется инициализатор переменной перед вызовом конструктора экземпляра базового класса. Однако значениеy
равно 0 (значение по умолчаниюint
), поскольку присвоение доy
не выполняется до тех пор, пока не вернется конструктор базового класса. Полезно подумать об инициализаторах переменных экземпляра и инициализаторы конструктора в качестве операторов, которые автоматически вставлены перед конструктором. Пример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; } }
содержит несколько переменных инициализаторов; он также содержит конструктор инициализаторы обеих форм (базы и этого). Пример соответствует код, показанный ниже, где каждый комментарий указывает автоматически вставленный оператор (синтаксис, используемый для автоматически вставленного вызовы конструктора недействительны, а просто служат для иллюстрируют механизм).
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; } }
Сначала будет вызываться базовый конструктор, иначе в случаях, когда ваш "другой материал" должен использовать переменные-члены, инициализированные вашим базовым конструктором, вы получите ошибки времени компиляции, потому что ваши члены класса еще не были инициализированы,
base (?) вызывается до того, как всякая работа выполняется в дочернем конструкторе.
Это верно, даже если вы оставьте значение: base() (в этом случае вызывается конструктор базы с 0 параметрами).
Он работает аналогично java,
public Child()
{
super(); // this line is always the first line in a child constructor even if you don't put it there! ***
}
*** Исключение: я мог бы добавить супер (1,2,3). Но если я не нахожу вызов супер в явном виде, вызывается super().
Конструкторские вызовы вызываются (снимаются) снизу вверх и выполняются сверху вниз. Таким образом, если у вас есть класс C, который наследует класс B, который наследует от класса A, при создании экземпляра класса C вызывается конструктор для C, который, в свою очередь, вызывает инструктора для B, который снова в свою очередь вызывает конструктор для A. Теперь выполняется конструктор для A, затем выполняется конструктор для B, тогда выполняется конструктор для C.