When you want to share initialization code among multiple constructors, there are generally two approaches.
Initialization Method
The first approach is to create a private initialization method that you call from each constructor:
public class Test { public Test( bool a, int b, string c ) { this.m_C = c; this.Initialize( a, b ); } public Test( bool a, int b, float d ) { this.m_D = d; this.Initialize( a, b ); } private void Initialize( bool a, int b ) { this.m_A = a; this.m_B = b; } private bool m_A; public bool A { get { return this.m_A; } } private int m_B; public int B { get { return this.m_B; } } private string m_C; public string C { get { return this.m_C; } } private float m_D; public float D { get { return this.m_D; } } }
Constructor Chaining
Another approach is to use constructor chaining, where a constructor calls another constructor in its class using the ": this()" designation as shown below:
public Test( bool a, int b, string c ) : this( a, b ) { this.m_C = c; } public Test( bool a, int b, float d ) : this( a, b ) { this.m_D = d; } private Test( bool a, int b ) { this.m_A = a; this.m_B = b; }
Chaining is Better
As described in Nazish Ahsan’s blog, constructor chaining is preferred over an initialization method because it eliminates duplicate code and supports readonly members.
The compiler automatically adds code to constructors to initialize variables and call the base class constructor. When you write your own common initialization function, the compiler duplicates this code in each constructor that calls the base constructor. Using constructor chaining so that you have only one constructor calling the base constructor will eliminate this duplicate code.
In addition, you can initialize readonly members only in a constructor and not in a method. So if the member m_A in our Test class is readonly, the first example would fail to compile since it tries to initialize the m_A readonly member in the Initialize method. This means you must either duplicate read-only initialization code in every constructor (bad idea) or use constructor chaining as shown in the second approach (good idea).
Also notice in the second example how the chained constructor "Test( bool a, int b)" is marked private, even though the constructors that call it are public. This allows you to hide chained constructors if desired.
[…] Constructor Chaining – C# 411 shows a nice way of making all your constructors share code. […]
Great example, I’ve linked to your example from an article I wrote as well.
http://www.pchenry.com/Home/tabid/36/EntryID/22/Default.aspx
Hello,
Allow me one question please:
– Once a Test object is created, I feel there’s a need for a method like this:
Initialize(a,b, c)
Test test = new Test(true,2,”3″);
test.Initialize(false,8,”9″);
test.Initialize(true,10,”11″);
How would you write the Initialize method in order to avoid copy paste code from the constructor ??
public Initialize( bool a, int b, string c )
{
this.m_A = a;
this.m_B = b;
this.m_C = c;
}
Charles, if I understand your question correctly, in your case you would call the Initialize method from your constructor so as not to duplicate the initialization code in your constructor and in the Initialize method. Although constructor chaining is preferred, you have an overriding requirement.
I agree with timm, keeping things DRY (Don’t Repeat Yourself) sometimes means refactoring things out of constructors into your own methods. Nothing wrong with it, especially since you have the F12 in Visual Studio to follow the method chain. :>
Hello,
1) I would like to chain constructors as shown below,
because in this way all the initialization logic is in just one place
private Test( bool a, int b )
: this( a, b, “”, -1 )
{
}
public Test( bool a, int b, string c )
: this( a, b, c, -1 )
{
}
public Test( bool a, int b, float d )
: this( a, b, “”, d )
{
}
public Test( bool a, int b, string c, float d )
{
this.m_A = a;
this.m_B = b;
this.m_C = c;
this.m_D = d;
}
2) I would like only the last constructor (with 4 parameters) to look like below:
Is it a problem for a performance point of view ?
public Test( bool a, int b, string c, float d )
{
Initialize(a, b, c, d);
}
public Initialize( bool a, int b, string c, float d )
{
this.m_A = a;
this.m_B = b;
this.m_C = c;
this.m_D = d;
}
Re: Is it a problem for a performance point of view?
No. You’re not likely to notice any performance difference unless you are looping billions of times.
Typically with C# you don’t want to waste much time micro-optimizing. In other words, just write the code you want and don’t worry too much about performance. Then once you have the code working the way you want it, if you notice any performance issues, use a profiler to identify trouble spots, then optimize the slow sections of code as necessary.
[…] Whenever I start a new “pet” project I usually *want* to use IoC, but I don’t really want the hassle of taking a dependency on a container, or adding another binary to my project. Usually this leaves me using “poor man’s IoC”, whereby I define dependencies in my constructors, but I pass them in manually or construct them using constructor chaining. […]
good concept but i wana little bit more
Nice article .. you can find more on
http://dotnetdrives.blogspot.com/2011/09/constructor-chainingin-csharp.html
[…] many things: eg silly easy things like object serialization, and constructor chaining. Too easy one forgets when not actively pumping out the […]
[…] Source Courtesy of csharp411.com […]