Will the base class constructor be automatically called?

C#ConstructorBase Class

C# Problem Overview


class Person
{
    public int age;
    public Person()
    {
        age = 1;
    }
}

class Customer : Person
{
    public Customer()
    {
        age += 1;
    }
}

Customer customer = new Customer();

Would the age of customer be 2? It seems like the base class's constructor will be called no matter what. If so, why do we need to call base at the end sometimes?

public Customer() : base()
{
    .............
}

C# Solutions


Solution 1 - C#

This is simply how C# is going to work. The constructors for each type in the type hierarchy will be called in the order of Most Base -> Most Derived.

So in your particular instance, it calls Person(), and then Customer() in the constructor orders. The reason why you need to sometimes use the base constructor is when the constructors below the current type need additional parameters. For example:

public class Base
{
     public int SomeNumber { get; set; }

     public Base(int someNumber)
     {
         SomeNumber = someNumber;
     }
}

public class AlwaysThreeDerived : Base
{
    public AlwaysThreeDerived()
       : base(3)
    {
    }
}

In order to construct an AlwaysThreeDerived object, it has a parameterless constructor. However, the Base type does not. So in order to create a parametersless constructor, you need to provide an argument to the base constuctor, which you can do with the base implementation.

Solution 2 - C#

Yes, the base class constructor will be called automatically. You do not need to add an explicit call to base() when there is a constructor with no arguments.

You can easily test this by printing out the age of the customer after construction (link to ideone with a demo).

Solution 3 - C#

If you did not have a default parameterless constructor then there would be a need to call the one with parameters:

class Person
{
    public Person(string random)
    {
 
    }
}

class Customer : Person
{
    public Customer(string random) : base (random)
    {

    }
}

Solution 4 - C#

Using your example, the answer is: YES. The base constructor will be called for you and you do not need to add one.

You are only REQUIRED to use "base(...)" calls in your derived class if you added a constructor with parameters to your Base Class, and didn't add an explicit default constructor.

You only need to make that base(...) call if you disrupt or break the implied constructor call chain to the base constructor from the derived class. That happens the minute you add a non-default constructor to your base class.

In c# using base and derived classes, some call to the base class's constructors must always be made from the derived class, either implicitly by the runtime, or explicitly by you. Most of the time the runtime will call the base class default constructor for you when you create your derived class object, so you do not need to call "base()". By default, a derived class when instantiated will always IMPLICITLY call the base class default constructor. That is why in most cases, you do NOT need to add "base()" to a derived class's constructor. A base class is always instantiated first from the derived class via a call to the default constructor in the base class, UNLESS you change its constructors (see below). C# doesn't care if it is a default constructor or non-default constructor with parameters. One must be called in the base class when the derived class object is created.

That is why you can leave out both a "base()" call in your derived class constructor and an explicit default constructor in all your classes as its implicitly called.

The implicit base class constructor call is only true and made for you if one of the following is true. When true, you do NOT need to call "base(...)" in your derived class:

  1. Your base class has no explicit constructors defined
  2. You base class has only an explicit default constructor defined
  3. You base class has one or more non-default constructors defined with parameters AND an explicit default constructor is defined.

When you suddenly add a non-default constructor with parameter(s) and NO default constructor, it breaks the default hidden default constructor chain creation and calls and you HAVE to add "base()". In your Base class with a non-default constructor you must now either call that constructor explicitly from the derived class using "base(...)", or add a default constructor explicitly in the base class. If the latter you can avoid "base()" calls. It is implicitly called.

Let's test this.....

// IMPLIED CONSTRUCTOR CALL TO THE BASE CLASS CALL WORKS NATURALLY HERE
class MyBaseClass0
{
// a default constructor added for you
}
class DerivedClass0 : MyBaseClass0
{
// an implied call to the base constructor is done for you
}

// THIS WORKS!!!
class MyBaseClass1
{
// a default constructor added for you
}
class DerivedClass1 : MyBaseClass1
{
    public DerivedClass1()
    {
      // Here the derived class default constructor is 
      // created explicitly but an implied call to the
      // base constructor is done for you
    }
}

// AND THIS WORKS!!!
class MyBaseClass2
{
// a default constructor added for you
}
class DerivedClass2 : MyBaseClass2
{
    public DerivedClass2() : base()
    {
    // "base()" is still optional here as implied call
    // to the base constructor is done for you
    }
}

// AND THIS WORKS!!!
class MyBaseClass3
{
// a default constructor added for you
}
class DerivedClass3 : MyBaseClass3
{
    public DerivedClass3(int x)// base not needed
    {
    // an implied call to the base constructor is still done for you
    }
}

// BECAUSE WE ADDED A NON-DEFAULT CONSTRUCTOR WITH
// NO EXPLICIT DEFAULT CONSTRUCTOR WE MUST USE "BASE(...)"

class MyBaseClass4
{
    // need explicit default constructor or must use "base()" now

    // non-default constructor added which breaks implicit call
    public MyBaseClass4(string y)
    {

    }
}
class DerivedClass4 : MyBaseClass4
{
    public DerivedClass4(int x) : base("hello")
    {
       // The implicit call to the default constructor is broken now
       // because we added a non-default constructor to base class.
       // Adding a "base()" call we have fulfilled the requirement
       // that some base constructor be called in the Base Class.
    }
}

// The IMPLIED default constructor call now works again
// because we added an explicit default constructor beside
// the non-default one we added. "base()" is not needed again.

class MyBaseClass5
{
    public MyBaseClass5()
    {
    }

    public MyBaseClass5(string y)
    {
    }
}
class DerivedClass5 : MyBaseClass5
{
    public DerivedClass5(string x)
    {
    }
}

Solution 5 - C#

base() is called by default but it can be used for other purpose such as :

  1. base()` method is used to pass the value to the parent class construct or
  2. to call the no-arg constructor of parent class .

for example:

Case 1: if parent have parametrized constructor but not default or no-arg constructor.

 class Person
 {

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;
        
    }
    }
class Employee : Person
{
    private double Salary { get; set; } = 0;

    public Employee(string firstName, string lastName, string emailAddress, DateTime dateOfBirth,double salary)
        :base(firstName,lastName,emailAddress,dateOfBirth)// used to pass value to parent constructor and it is mandatory if parent doesn't have the no-argument constructor.
    {
        Salary = salary;
    }
}

Case 2: when parent have more than one constructor along with default one.

class Person
{

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person()
    {
        // some important intialization's to be done  
        
    }

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;
        
    }
    }
class PermanentEmployee : Person
{
    public double HRA { get; set; }
    public double DA { get; set; }
    public double Tax { get; set; }
    public double NetPay { get; set; }
    public double TotalPay { get; set; }

    public PermanentEmployee(double hRA, double dA, double tax, double netPay, double totalPay) : base();
    {
        HRA = hRA;
        DA = dA;
        Tax = tax;
        NetPay = netPay;
        TotalPay = totalPay;
    }
}

Here we are calling a no-arg constructor manually by base() to perform some intilizations but doesn'e passed any value.

Hope this will help you.

Solution 6 - C#

I don't have much to add, but I have found that I need to call MyConstructor() : base() with no params in 1 case. I have a base class that implements INotifyPropertyChanged in a way where I have a RegisterProperties() virtual function. When I override it, it is called in the base constructor. So I end up having to call it in the most recently derived subclasses because the base was apparently called before the overridden virtual was recognized. My properties don't notify unless I do this. The entire base class is below.

I added a DatabaseTraits subclass directly below it. Without the empty base() call, my properties don't call OnPropertyChanged().

[DataContract]
public abstract class DataModelBase : INotifyPropertyChanged, IDataErrorInfo {

    #region Properties

    [IgnoreDataMember]
    public object Self {
        get { return this; }
        //only here to trigger change
        set { OnPropertyChanged("Self"); }
    }

    #endregion Properties

    #region Members

    [IgnoreDataMember]
    public Dispatcher Dispatcher { get; set; }

    [DataMember]
    private Dictionary<object, string> _properties = new Dictionary<object, string>();

    #endregion Members

    #region Initialization

    public DataModelBase() {
        if(Application.Current != null) Dispatcher = Application.Current.Dispatcher;
        _properties.Clear();
        RegisterProperties();
    }

    #endregion Initialization

    #region Abstract Methods

    /// <summary>
    /// This method must be defined
    /// </summar
    protected abstract void RegisterProperties();

    #endregion Abstract Methods

    #region Behavior

    protected virtual void OnPropertyChanged(string propertyName) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected bool RegisterProperty<T>(ref T property, string propertyName) {
        //causes problems in design mode
        //if (property == null) throw new Exception("DataModelBase.RegisterProperty<T> : ref T property cannot be null.");
        if (_properties.ContainsKey(property)) return false;

        _properties.Add(property, propertyName);

        return true;
    }

    protected string GetPropertyName<T>(ref T property) {
        if (_properties.ContainsKey(property))
            return _properties[property];

        return string.Empty;
    }

    protected bool SetProperty<T>(ref T property, T value) {
        //if (EqualityComparer<T>.Default.Equals(property, value)) return false;
        property = value;
        OnPropertyChanged(GetPropertyName(ref property));
        OnPropertyChanged("Self");

        return true;
    }

    [OnDeserialized]
    public void AfterSerialization(StreamingContext context) {
        if (Application.Current != null) Dispatcher = Application.Current.Dispatcher;
        //---for some reason this member is not allocated after serialization
        if (_properties == null) _properties = new Dictionary<object, string>();
        _properties.Clear();
        RegisterProperties();
    }

    #endregion Behavior

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion INotifyPropertyChanged Members

    #region IDataErrorInfo Members

    string IDataErrorInfo.Error {
        get { throw new NotImplementedException(); }
    }

    string IDataErrorInfo.this[string propertyName] {
        get { throw new NotImplementedException(); }
    }

    #endregion IDataErrorInfo Members

} //End class DataModelBaseclass DataModelBase

/*I decided to add an example subclass*/
    [DataContract]
public abstract class DatabaseTraits : DataModelBase {
    #region Properties
    private long _id = -1;
    [DataMember]
    public long Id {
        get { return _id; }
        set { SetProperty(ref _id, value); }
    }
    private bool _isLocked = false;
    [DataMember]
    public bool IsLocked {
        get { return _isLocked; }
        set { SetProperty(ref _isLocked, value); }
    }

    private string _lockedBy = string.Empty;
    [DataMember]
    public string LockedBy {
        get { return _lockedBy; }
        set { SetProperty(ref _lockedBy, value); }
    }

    private DateTime _lockDate = new DateTime(0);
    [DataMember]
    public DateTime LockDate {
        get { return _lockDate; }
        set { SetProperty(ref _lockDate, value); }
    }

    private bool _isDeleted = false;
    [DataMember]
    public bool IsDeleted {
        get { return _isDeleted; }
        set { SetProperty(ref _isDeleted, value); }
    }
    #endregion Properties

    #region Initialization
    public DatabaseTraits() : base() {
        /*makes sure my overriden RegisterProperties() is called.*/
    }
    protected override void RegisterProperties() {
        RegisterProperty(ref _id, "Id");
        RegisterProperty(ref _isLocked, "IsLocked");
        RegisterProperty(ref _lockedBy, "LockedBy");
        RegisterProperty(ref _lockDate, "LockDate");
        RegisterProperty(ref _isDeleted, "IsDeleted");
    }
    #endregion Initialization

    #region Methods
    public void Copy(DatabaseTraits that) {
        Id = that.Id;
        IsLocked = that.IsLocked;
        LockedBy = that.LockedBy;
        LockDate = that.LockDate;
        IsDeleted = that.IsDeleted;
    }
    #endregion Methods
}

Solution 7 - C#

Simpliest way to test private methods with NUnit or xUnit

I can suggest next:

  1. make them protected
  2. create private mock class,
  3. derive it from class which we want to test
  4. add new public method that calls base method.
public class Car
{
    protected void StartEngine() {}

    protected void StartMoving() {}

    public void Drive()
    {
        StartEngine();
        StartMoving();
    }
}


public class TestClass
{
    [Test]
    public void Test1()
    {
        var mock = new MockCar();
        mock.StartEngine();
        mock.StartMoving();
    }

    private class MockCar : Car
    {
        public new void StartEngine()
        {
            base.StartEngine();
        }

        public new void StartMoving()
        {
            base.StartMoving();
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionIvan LiView Question on Stackoverflow
Solution 1 - C#TejsView Answer on Stackoverflow
Solution 2 - C#Sergey KalinichenkoView Answer on Stackoverflow
Solution 3 - C#Science_FictionView Answer on Stackoverflow
Solution 4 - C#StokelyView Answer on Stackoverflow
Solution 5 - C#MinionView Answer on Stackoverflow
Solution 6 - C#steviesamaView Answer on Stackoverflow
Solution 7 - C#Leonid PavlovView Answer on Stackoverflow