2008-09-26 3 views

ответ

92

Базовый конструктор будет вызван в первую очередь.

попробовать:

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

public class MyDerived : MyBase 
{ 
    public MyDerived():base() 
    { 
    Console.WriteLine("MyDerived"); 
    } 
} 
+1

Вы правы. Но выполнение начинается с производного конструктора, первое, что делает производный конструктор, - это вызов базового конструктора (если он есть). Таким образом, кажется, что сначала вызывается базовый конструктор. – 2017-08-16 14:50:58

3

Я бы сказал, что база

EDIT см:

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

там говорит:

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

производный класс

17

На самом деле, производный класс конструктор выполняется первым, но C# компилятор вставляет вызов конструктора базового класса в качестве первого оператора производного конструктора ,

Итак: производный выполняется первым, но он «похож» на то, что база была выполнена первой.

+2

Это один из тех случаев, когда контекст важен - в терминах CLR выполняется первый производный конструктор. В терминах C# сначала выполняется базовый конструктор. Есть несколько таких странностей, когда спецификации не согласуются; например, о том, имеют ли структуры конструктор без параметров или нет. – 2008-09-26 16:55:22

+6

На самом деле, похоже, я говорил слишком быстро.Теперь я просмотрел спецификацию, и в то время как он говорит, что инициализатор конструктора выполняется до тела конструктора, который считается включенным в общий конструктор. Таким образом, вы совершенно правы с обеих сторон :) – 2008-09-26 17:02:57

127

Конструкторы базового класса вызываются перед конструкторами производных классов, но инициализаторы производных классов вызываются перед инициализаторами базового класса. Например. в следующем коде:

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:

0

Базовый конструктор будет называться первым, иначе, в случаях, когда e ваш «другой материал» должен использовать переменные-члены, инициализированные вашим базовым конструктором, вы получите ошибки времени компиляции, потому что ваши члены класса еще не были инициализированы.

+0

Элементы-члены не имеют той же концепции определенного назначения, что и локальные переменные. Они имеют значение по умолчанию. Что интересно в C#, так это то, что инициализаторы переменных запускаются * перед * базовым конструктором, а не после. (Java имеет последнее поведение.) – 2008-09-26 16:37:45

0

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().

+0

Это немного отличается от Java из-за порядка инициализаторов переменных. Подробнее см. Http://pobox.com/~skeet/csharp/constructors.html. – 2008-09-26 16:35:51

4

Как уже говорилось, базовый конструктор называется первым. Однако конструкторы на самом деле не первое, что происходит.

Допустим, у вас есть классы, как это:

class A {} 

class B : A {} 

class C : B {} 

Во-первых, поле Инициализаторы будет называться в порядке наиболее полученных наименее производных классов. Итак, первые инициализаторы полей C, затем B, затем A.

Конструкторы затем будут вызываться в обратном порядке: первый конструктор A, затем B, затем C.

0

Конструкторские вызовы вызываются снизу вверх и выполняются сверху вниз. Таким образом, если у вас есть класс C, который наследует класс B, который наследует от класса A, при создании экземпляра класса C вызывается конструктор для C, который, в свою очередь, вызывает инструктора для B, который снова в свою очередь вызывает конструктор для A. Теперь выполняется конструктор для A, затем выполняется конструктор для B, тогда выполняется конструктор для C.

30

Не пытайтесь запомнить его, попробуйте объяснить себе, что должно произойти. Представьте, что у вас есть базовый класс с именем Animal и производным классом Dog. Полученный класс добавляет некоторые функциональные возможности базовому классу. Поэтому, когда выполняется конструктор производного класса, экземпляр базового класса должен быть доступен (чтобы вы могли добавить к нему новые функции). Вот почему конструкторы выполняются из базы в производную, но деструкторы выполняются в обратном порядке - сначала производные деструкторы, а затем базовые деструкторы.

(Это упрощенная, но это должно помочь вам ответить на этот вопрос в будущем без необходимости фактически запоминая это.)

1

Base Конструктор называется первым. Но инициализатор полей в производном классе называется первым.

Порядок призвание

  1. производный класс поля инициализатор
  2. основное поле класса инициализатор
  3. конструктор базового класса
  4. производного класса конструктор

(Вы можете лечить 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; 
    } 
} 
Смежные вопросы