Reputation: 12574
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.
Upvotes: 9
Views: 3158
Reputation: 107237
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
Upvotes: 1
Reputation: 2576
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.
Upvotes: 7
Reputation: 4551
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()
Upvotes: 2
Reputation: 11385
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.
Upvotes: 2