C#: порядок вызова конструктора

рассмотрим следующий код:

код

public class RecursiveConstructor
{
   //When this constructor is called 
   public RecursiveConstructor():this(One(), Two())
   {
       Console.WriteLine("Constructor one. Basic.");
   }

   public RecursiveConstructor(int i, int j)
   {
       Console.WriteLine("Constructor two.");
       Console.WriteLine("Total = " + (i+j));
   }

   public static int One()
   {
       return 1;
   }

   public static int Two()
   {
       return 2;
   }
}

вызов метода

public class RecursiveConstructorTest
{
    public static void Main()
    {
        RecursiveConstructor recursiveConstructor = new RecursiveConstructor();

        Console.ReadKey();
    }
}

Результат

два конструктора.

Итого = 3

конструктор один. Основной.

почему сначала запускается 2-й конструктор?

Я понимаю, что в цепных конструкторах мы сначала вызываем конструктор базового класса, а затем сделайте наш путь назад по цепочке, но когда конструктор удерживается в том же классе, почему мы все еще видим это поведение, когда сначала вызывается дополнительный конструктор?

Я бы подумал, что сначала будет выполнено самое основное содержимое конструктора.

4 ответов


Я думаю, что компилятор запускает более безопасный сценарий. Если вы вызываете другой конструктор здесь, есть вероятность, что этот другой конструктор является обязательное условие к вашему текущему конструктор. Это поведение согласуется с тем, которое предоставляется при вызове базовых конструкторов, и тогда следует ожидать.

при создании нового экземпляра класса существует цепочка конструкторов, которые вызываются от наименее специализированных (конструктор класса объектов) до наиболее специализированных specialized (конструктор вашего текущего класса).

оператор : позволяет явно добавить конструктор к этой цепи, поэтому этот порядок кажется естественным.


вы сами дали объяснение. Почти так же называются базовые конструкторы. При вызове конструктора в вашей подписи, например

 public RecursiveConstructor() : this(One(), Two())

или

 public RecursiveConstructor() : base()

конструктор сразу после : вызывается первой.


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

две формы инициализатора конструктора, : base(...), который часто имплицитно называют, и : this(...) вести себя так же.

Итак, в вашем случае у нас есть цепочка:

Object()

затем...

RecursiveConstructor(int i, int j)

затем...

RecursiveConstructor()

сначала вызывается конструктор 1, но ctor1 называет ctor2 прежде чем он попадет в блок кода ctor1, следовательно, вывод, который вы видите.

один из способов обойти это, но сохранить сухое поведение было бы рефакторингом (int, int) перегрузка:

   //When this constructor is called 
   public RecursiveConstructor()
   {
       Console.WriteLine("Constructor one. Basic.");
       Init(One(), Two());
   }

   public RecursiveConstructor(int i, int j)
   {
       Console.WriteLine("Ctor 2");
       Init(i, j);
   }


   private void Init(int i, int j)
   {
       Console.WriteLine("Refactored");
       Console.WriteLine("Total = " + (i+j));
   }

из интереса, цепные конструкторы таким образом часто называют "делегирование конструкторов'.

в Java можно поместить вызов на другой конструктор в блоке кода (например,посмотреть здесь), но это должна быть первая строка в блоке