9

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.

Vishal Suthar
  • 17,013
  • 3
  • 59
  • 105
CSharpened
  • 11,674
  • 14
  • 52
  • 86
  • 11
    By the way, this isn't recursive. – Ian Newson Aug 28 '12 at 09:05
  • I think that is still constructor chaining. – mbm Aug 28 '12 at 09:09
  • Thanks. It was my mistake to think it was a recursive constructor. I have approved the edit to the title. So what we are looking at here is essentially constructor chaining but within the same class rather than across inherited and base classes? – CSharpened Aug 28 '12 at 09:18
  • 1
    It's not completely clear to me what you're asking - "Why is the 2nd constructor run first?" - because you've *asked* that the second be run first! If you want different behaviour, you'll need to write different code. – AakashM Aug 28 '12 at 09:20

4 Answers4

7

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.

dureuill
  • 2,526
  • 17
  • 24
  • also: even if you don't write it as such explicitly, the default `base()` constructor is always called before the class' constructor, so appending `: this(..)` will therefore also get called first. it's in line with the bahavior that was already there implicitly. – mtijn Aug 28 '12 at 09:13
  • 1
    Yes this is a dependency chain. The `:` operator is used to explicity add elements to this dependency chain. – dureuill Aug 28 '12 at 09:18
2

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.

oopbase
  • 11,157
  • 12
  • 40
  • 59
  • Is there a reason that this was coded this way in the framework? – CSharpened Aug 28 '12 at 09:05
  • 1
    The "raw", parameterless constructor could (for example) initialize some properties or fields (whose values could be set in parameterized constructor then without throwing null reference exception). – Konrad Morawski Aug 28 '12 at 09:07
  • @CSharpened I have no explanation why it is coded this way. The inner implementation probably calls the constructor after the ":" immediately, like in java. There it is also common to call "super()" or "this()" as first keyword after the signature. – oopbase Aug 28 '12 at 09:08
  • 1
    @CSharpened I guess you would want to have the ability to call a more specific constructor from your default constructor to be able to be able to pass default values. Calling it using `:` also does all the other instantiation so you know the class is first constructed before you use the more general settings. If you'd wanted to you could also call you more specific constructor in your default constructor of course. – Nebula Aug 28 '12 at 09:08
2

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()
cspolton
  • 4,495
  • 4
  • 26
  • 34
1

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 (e.g. see here), but it must be the first line in the block

Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285