9

考虑以下代码:

编码

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

构造函数一。基本的。

为什么第二个构造函数首先运行?

我知道在链式构造函数中,我们首先调用基类构造函数,然后沿着链返回,但是当构造函数保存在同一个类中时,为什么我们仍然会看到首先调用额外构造函数的这种行为?

我原以为会首先执行最基本的构造函数内容。

4

4 回答 4

7

我认为编译器运行更安全的场景。如果你在这里调用另一个构造函数,那么这个构造函数很可能是你当前构造函数的先决条件。这种行为与调用基本构造函数时暴露的行为一致,并且是可以预料的。

当创建一个类的新实例时,有一系列构造函数被调用,从最不专业的(对象类的构造函数)到最专业的(当前类的构造函数)。

运算符:允许您显式地将构造函数添加到此链中,因此此顺序看起来很自然。

于 2012-08-28T09:07:49.070 回答
2

你自己给出了解释。调用基本构造函数的方式几乎相同。每当在签名中调用构造函数时,例如

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

或者

 public RecursiveConstructor() : base()

紧随其后的构造函数:首先被调用。

于 2012-08-28T09:04:39.770 回答
2

当您考虑到在初始化新对象时总是有一个层次结构的构造函数调用链时,这是有道理的。正如您所说的那样,首先调用基类构造函数。

构造函数初始化器的两种形式,: base(...)通常被隐式调用,并且: this(...)行为方式相同。

因此,在您的情况下,我们有一个链:

Object()

然后...

RecursiveConstructor(int i, int j)

然后...

RecursiveConstructor()
于 2012-08-28T09:16:07.057 回答
1

它首先调用构造函数 1,但ctor1在到达 ctor1 代码块之前调用ctor2 ,因此您会看到输出。

解决这个问题的一种方法,但要保留 DRY 行为是重构(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 中,可以在代码块中调用另一个构造函数(例如,参见此处),但它必须是代码块中的第一行

于 2012-08-28T09:09:00.877 回答