69. Constructor chaining#

We’ve already talked about constructors and constructor overloading but let’s now talk about constructor chaining. This is a technique where a constructor in a class calls another constructor in the same class or a constructor in its superclass. It allows for code reusability and is a neat way to initialize an object with different sets of parameters.

Consider a Rectangle class where one constructor accepts two arguments, width and height, while another only takes a side length and treats the rectangle as a square.

public class Rectangle
{
    public double Width { get; set; }
    public double Height { get; set; }

    // Constructor for rectangle
    public Rectangle(double width, double height)
    {
        Console.WriteLine("Running constructor with 2 parameters.");
        this.Width = width;
        this.Height = height;
    }

    // Constructor for square
    public Rectangle(double side)
        : this(side, side) // This calls the first constructor
    {
        Console.WriteLine("Running constructor with 1 parameter.");
    }
}

In the case above, the Rectangle constructor with one argument, side, invokes the two-argument constructor, assuming the rectangle to be a square, with equal width and height.

Note

When chaining constructors using this or base we have to supply the arguments for the parameters that the constructor in question is expecting. To do so we are allowed to write expressions. In these expressions we also have access to the arguments that was passed to the constructor doing the chaining. In the example above, we are passing on the argument side.

When we call the constructor which takes two arguments, only that constructor is run.

new Rectangle(10, 10);
Running constructor with 2 parameters.

But when we run the constructor which takes one argument, that constructor also invokes the other constructor:

new Rectangle(10);
Running constructor with 2 parameters.
Running constructor with 1 parameter.

Tip

Note that the constructor we delegate to is run before the constructor doing the delegating.

Let’s now look at constructor chaining with a superclass. In a class hierarchy, when you instantiate an object of a derived class, the constructors are called in order from the top-most base class down to the most derived class. Each constructor does its part in initializing the object. If one constructor in the chain explicitly calls another using the base keyword, that called constructor runs before the calling constructor continues its execution. This guarantees that the object is fully initialized at each level of the inheritance hierarchy before it’s further initialized at the next level.

Say that we have a Vehicle class and a derived Car class. The Vehicle constructor accepts a maxSpeed parameter, and the Car class adds a color property:

public class Vehicle
{
    public double MaxSpeed { get; private set; }

    public Vehicle(double maxSpeed)
    {
        Console.WriteLine("Running constructor in parent.");
        this.MaxSpeed = maxSpeed;
    }
}
public class Car : Vehicle
{
    public string Color { get; private set; }

    // Constructor
    public Car(double maxSpeed, string color) : base(maxSpeed)
    {
        Console.WriteLine("Running constructor in child.");
        this.Color = color;
    }
}

In this scenario, the Car class’s constructor uses the base keyword to call the Vehicle class’s constructor. The Vehicle constructor initializes the MaxSpeed property, and the Car constructor then initializes the Color property.

Just like when we chained constructors in the same class, when we run the constructor that delegates to another constructor through constructor chaining, then both constructors are invoked. Again, notice that the constructor we delegate to is run before the constructor doing the delegating.

new Car(120, "Red");
Running constructor in parent.
Running constructor in child.

Since the constructor in Car is the one doing the chaining, only a single constructor is run if we instead instantiate a Vehicle.

new Vehicle(120);
Running constructor in parent.

Notice that the Vehicle superclass doesn’t provide a parameterless constructor. If we were to define a Car subclass and try to provide a constructor without using the base keyword to call the superclass’s constructor, we would run into a problem.

Important

When a superclass does not have a parameterless constructor, subclasses must explicitly call one of the available constructors using the base keyword.

public class Car : Vehicle
{
    public string Color { get; set; }
    public Car(string color) => this.Color = color;
}
(4,12): error CS7036: There is no argument given that corresponds to the required parameter 'maxSpeed' of 'Vehicle.Vehicle(double)'

This leads to a compilation error. The compiler complains that we have not provided an argument for the parameter maxSpeed in the constructor of Vehicle. By ensuring that the Car class’s constructor calls the Vehicle class’s constructor with a maxSpeed parameter using the base keyword, as we did when we did call base, we satisfy the compiler, and the code compiles successfully.

Key point

Constructor chaining allows a constructor to call another constructor, either within the same class or in its superclass, using the this or base keywords respectively. This technique leads to cleaner code by eliminating duplication and ensuring all necessary initialization always takes place, no matter which constructor is called. When a superclass does not have a parameterless constructor, subclasses must explicitly call one of the available constructors using the base keyword.