Reputation: 587
NOTE: I'm working in .NET 3.5 here.
Let's say I have sample base/child classes with the following constructors:
public Person(string name, int age, string job, bool isMale)
{
Name = name;
Age = age;
Job = job;
IsMale = isMale;
}
public CollegeStudent(string name) : this(name, 18) {}
public CollegeStudent(string name, int age) : this(name, age, "Student") {}
public CollegeStudent(string name, int age, string job) : this(name, age, job, true) {}
public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) {}
Is the compiler smart enough to see that the only thing that the child constructors are doing are chaining to each other and ultimately just calling the base constructor? So, it could just change the "this" constructor initializers to call the base constructor directly at compile time?
So it would essentially change everything to this under the hood:
public CollegeStudent(string name) : base(name, 18, "Student", true) {}
public CollegeStudent(string name, int age) : base(name, age, "Student", true) {}
public CollegeStudent(string name, int age, string job) : base(name, age, job, true) {}
public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) {}
I would like to write my constructors similarly to the first section since it is convenient, but I may just call the base constructor directly for each constructor if I'm just going to incur useless overhead.
Upvotes: 3
Views: 728
Reputation: 29658
The C# compiler will walk backwards down the line of chained constructors until it reaches the constructor for Object
. I don't think there is much to optimize when it comes to chained constructors, as you are using them. To find out for yourself, you can could try compiling that code and then use Reflector to take a peek at the optimized code.
Until then, I wait for Jon Skeet.
Edit
I just compiled this simple code into a class (.Net 3.5):
namespace Person {
public class Person {
private String Name;
private int Age;
private String Job;
private Boolean IsMale;
public Person(string name, int age, string job, bool isMale) {
Name = name;
Age = age;
Job = job;
IsMale = isMale;
}
}
public class CollegeStudent : Person {
public CollegeStudent(string name) : this(name, 18) { }
public CollegeStudent(string name, int age) : this(name, age, "Student") { }
public CollegeStudent(string name, int age, string job) : this(name, age, job, true) { }
public CollegeStudent(string name, int age, string job, bool isMale) : base(name, age, job, isMale) { }
}
}
Using Reflector, I found that the C# compiler did not optimize any of the constructors in the way you suggested.
Upvotes: 6
Reputation: 1502806
If anything's going to optimize this, it should be the JIT compiler, not the C# compiler. In particular, if this is being called from a different assembly, the C# compiler can't assume that the code in CollegeStudent will be the same at execution time as it is at compile time.
As SimpleCoder and Jim say, you shouldn't worry too much about this. The chances of it being a significant performance problem are tiny.
As Mahesh says, with C# 4 you can use a single constructor with optional parameters, but you should be aware that even if you target .NET 2.0 or .NET 3.5, anyone compiling against your code with a C# 2 or C# 3 compiler won't be able to use the fact that some parameters are optional, and will be forced to specify all of them.
Upvotes: 6
Reputation: 134065
I don't know if the compiler is smart enough to eliminate the "useless overhead" of constructors chaining to each other. But does it really matter? The question you have to ask yourself is if the few microseconds potentially saved by writing the second version is really worth the cost in maintainability. Will you really be doing that many constructor calls that those few microseconds per call is going to matter. At all?
Upvotes: 2
Reputation: 21971
If you are using C# 4.0, use optional parameters, which are more convenient as well as terse.
public Person(string name, int age = 18, string job = "Student", bool isMale = true)
{
Name = name;
Age = age;
Job = job;
IsMale = isMale;
}
Now you can use,
public CollegeStudent(string name) : base(name) {}
public CollegeStudent(string name, int age) : base(name, age) {}
public CollegeStudent(string name, int age, string job) : base(name, age, job) {}
public CollegeStudent(string name, int age, string job, bool isMale)
: base(name, age, job, isMale) {}
Upvotes: 3
Reputation: 26505
Are you aware of the new syntax:
CollegeStudent student = new CollegeStudent
{
Name = "Bob",
Age = 21,
Job = "Spaceman",
IsMale = true,
};
Constructors like that should be unnecessary these days, unless you're have to compile in an older version of Visual Studio.
Upvotes: 1