简体   繁体   中英

C#: Order of Constructor call

Consider the following code:

The code

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

The calling method

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

        Console.ReadKey();
    }
}

The Result

Constructor two.

Total = 3

Constructor one. Basic.

Why is the 2nd constructor run first?

I understand that in chained constructors we call the base class constructor first and then make our way back up the chain but when the constructor is held in the same class why do we still see this behaviour where the extra constructor is called first?

I would have thought that the most basic constructor contents would be executed first.

I think the compiler runs the safer scenario. If you call another constructor here, there are chances that this other constructor is a prerequisite to your current constructor. This behaviour is consistent with the one exposed when calling base constructors, and is then to be expected.

When creating a new instance of a class, there is a chain of constructors that get called from the least specialized (the constructor of the object class) to the most specialized (the constructor of your current class).

The operator : allows you to explicitly add a constructor to this chain, so this order seems natural.

You gave the explanation yourself. It is almost the same way base constructors are called. Whenever calling a constructor in your signature, like

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

or

 public RecursiveConstructor() : base()

the constructor right after the : is called first.

It makes sense when you consider that there is always a hierarchical chain of constructor calls when initializing new objects. As you rightly say, the base classes constructor is called first.

The two forms of constructor initializer, : base(...) , which is often implictly called, and : this(...) behave the same way.

So, in your case we have a chain:

Object()

then...

RecursiveConstructor(int i, int j)

then...

RecursiveConstructor()

It is calling constructor 1 first, but ctor1 is calling ctor2 before it hits the ctor1 code block, hence the output you see.

One way around this, but to retain the DRY behaviour would be to refactor the (int, int) overload:

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

Out of interest, chaining constructors this way is often referred to as ' delegating constructors '.

In Java, it is possible to place the call to the other constructor in the code block (eg see here ), but it must be the first line in the block

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM