I was surprised to find out that the parameter-less constructor of my base class is called any time I call any constructor in a derived class. I thought that is what : base()
was for, to explicitly call the base constructor if and when I want to.
How can I prevent the base constructor from being called when I instantiate a derived class?
using System;
namespace TestConstru22323
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer("Jim", "Smith");
Customer c = new Customer();
Console.WriteLine(customer.Display());
Console.ReadLine();
}
}
public class Person
{
public Person()
{
Console.WriteLine("I don't always want this constructor to be called. I want to call it explicitly.");
}
}
public class Customer : Person
{
private string _firstName;
private string _lastName;
//public Customer(string firstName, string lastName): base() //this explicitly calls base empty constructor
public Customer(string firstName, string lastName) //but this calls it anyway, why?
{
_firstName = firstName;
_lastName = lastName;
}
public string Display()
{
return String.Format("{0}, {1}", _lastName, _firstName);
}
}
}
You could make the default base constructor
protected
, then have only non-default constructors for the base and its child.edit
You could give the base a
protected
constructor with a different signature (such as a protected enum type), and put your initialization code in there, while the default constructor, alsoprotected
, does not particular initialization.Your requirement to only need to call the constructor for some derived objects is not in line with the object-oriented principles. If it's a Person, then it needs to be constructed as such.
If you need shared initialization for some objects, then you should consider creating an
Initialize
method or adding a parameterized constructor that will be called by the specific derived objects.The parameterized constructor approach feels a little awkward:
One way would be to make your base default constructor private, but that only works if you make a helper constructor in the base class that calls the private one when you need it explicitly.
This is really contrived, and @aakashm has the best answer.
The only way is to explicitly tell it which other base ctor you want it to call; which of course means you must choose some base ctor to call.
You can't have it call no base ctor at all - conceptually, constructing a
Customer
is done by first constructing aPerson
, and then doingCustomer
specific construction on top of it. For example, supposePerson
hadprivate
fields - how would these be correctly constructed if construction of aCustomer
was allowed to not first construct aPerson
?In .NET, every object constructor in an object hierarchy will be called regardless if you call
:base()
or not.:base()
is implicitly called if you don't explicitly call it.:base()
can be used if you want to call a different contructor on a parent object rather than the default constructor.If you have code in the parent constructor that should not be called everytime, it may be better to move that code to it's own method that will need to be called explicitly after the object is constructed. Or, create a parameterized constructor on the parent object and use the parameter to determine if the code should be executed or not.
For example:
When you instantiate a class all the classes in the inheritance hierarchy are instantiated starting from the topmost Parent to the lowermost child, stopping at the type you instantiated. So if you instantiate System.Text.StringBuilder(), first you call the default constructor of System.Object, then StringBuilder(). You can use the base keyword to call a different constructor (one with equal or fewer params), but not more params. If you do not specify base, the default constructor is called, thus the reason this is happening to you. You can also use the base keyword within the context of an instance method to call base implementations, such as in the case of the decorator pattern. If you do not want to call the base class private constructors then you should set the children with private default constructors and also explicitly call base(params) on your other constructors.