Radi Atanassov

SharePoint MCM, MVP, MCT and owner of OneBit Software

Design smell: call overridable methods in constructors

This is another good question I got while teaching the C# Advanced course at SoftUni. Here is a detailed answer.

Question

Why shouldn't we call virtual methods within the constructor of a base class?

Answer

This is actually one of the Code Quality warnings under the Usage section. Please see the link here: https://docs.microsoft.com/en-us/visualstudio/code-quality/ca2214-do-not-call-overridable-methods-in-constructors?view=vs-2017

While the article is correct, I'm not sure the explanation is very understandable.

It all comes down to the following execution path:

  • You instantiate the derived class
  • The base class constructor is called
  • It calls virtual methods overridden in the derived class
  • But our derived class's constructor has not been called yet

Here is my example:

    public abstract class BaseClass
    {
        public BaseClass()
        {
            Console.WriteLine("BaseClass constructor called.");
 
            VirtualMethod();
            AbstractMethod();
        }
 
        public virtual void VirtualMethod()
        {
            Console.WriteLine("Base virtual method called");
        }
 
        public abstract void AbstractMethod();
    }


    public class DerivedClass : BaseClass
    {
        public DerivedClass()
        {
            Console.WriteLine("Derived class constructor executed VERY late.");
        }
 
        public override void VirtualMethod()
        {
            base.VirtualMethod();
 
            Console.WriteLine("Derived Virtual Method");
        }
 
        public override void AbstractMethod()
        {
            Console.WriteLine("Derived Abstract Method");
        }
    }

 

The result:

BaseClass constructor called.

Base virtual method called

Derived Virtual Method

Derived Abstract Method

Derived class constructor executed VERY late.

 

So we just ran code in a class which might very well be in an invalid state. Objects should go through construction logic first before we execute their methods.

 

Add comment

Loading