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();
    }
}

結果

コンストラクター 2。

合計 = 3

コンストラクター 1。基本。

2番目のコンストラクターが最初に実行されるのはなぜですか?

チェーンされたコンストラクターでは、最初に基本クラスのコンストラクターを呼び出してから、チェーンを元に戻すことを理解していますが、コンストラクターが同じクラスに保持されている場合、追加のコンストラクターが最初に呼び出されるこの動作がまだ見られるのはなぜですか?

最も基本的なコンストラクターの内容が最初に実行されると思っていたでしょう。

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(...)多くの場合、暗黙的に呼び出されるコンストラクタ初期化子の 2 つの形式は: this(...)、同じように動作します。

したがって、あなたの場合、チェーンがあります:

Object()

それから...

RecursiveConstructor(int i, int j)

それから...

RecursiveConstructor()
于 2012-08-28T09:16:07.057 に答える
1

最初にコンストラクター 1 を呼び出していますが、ctor1はctor1 コード ブロックに到達する前に ctor2 を呼び出しているため、出力が表示されます

これを回避する 1 つの方法ですが、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 に答える