Question

Why Calling a Virtual Member in a Constructor Is Risky in C#

csharpconstructorwarningsresharpervirtual-functions

Question

I am getting a ReSharper warning about calling a virtual member from my object's constructor.

Why is calling a virtual member inside a constructor considered something to avoid in C#?

Short Answer

By the end of this page, you will understand why calling a virtual member from a constructor can be dangerous in C#, especially when inheritance is involved. You will see what happens during object construction, why overridden methods can run before a derived class is fully initialized, and which safer patterns developers use instead.

Concept

In C#, virtual members allow derived classes to override behavior from a base class. Normally, that is useful because the runtime chooses the most specific implementation for the actual object type.

However, constructors are a special case.

When a base class constructor runs, the derived class part of the object has not finished initializing yet. If the base constructor calls a virtual method, and that method is overridden in a derived class, the derived override may run too early.

That means the override could access:

  • fields that are not initialized yet
  • properties that still have default values
  • dependencies that the derived constructor has not assigned
  • logic that assumes the object is fully ready

This can lead to:

  • NullReferenceException
  • incorrect values being used
  • partially constructed objects behaving unpredictably
  • hard-to-find bugs in inheritance hierarchies

This matters in real programming because object construction should create a valid, stable object. Calling overridable behavior during construction breaks that expectation by letting subclass-specific code run before subclass initialization is complete.

In short:

  • virtual means behavior can change in subclasses
  • constructors run from base to derived
  • therefore, a base constructor can accidentally trigger derived logic too early

Mental Model

Think of object construction like building a house in layers.

  • The base class constructor lays the foundation.
  • The derived class constructor adds the rooms, wiring, and furniture.

A virtual call in the base constructor is like inviting someone into the house and asking them to use the kitchen before the kitchen has been installed.

Because the runtime sees the final object type, it may send the call to the derived class override. But the derived class is not finished setting itself up yet.

So even though the object looks like a derived object, it is still only partially built.

Take Quiz

Syntax and Examples

In C#, a virtual method can be overridden in a derived class:

class Animal
{
    public Animal()
    {
        Speak(); // risky: virtual call in constructor
    }

    public virtual void Speak()
    {
        Console.WriteLine("Animal sound");
    }
}

class Dog : Animal
{
    private string name;

    public Dog()
    {
        name = "Rex";
    }

    public override void Speak()
    {
        Console.WriteLine(name.ToUpper());
    }
}

If you create a Dog:

var dog = new Dog();

The base constructor Animal() runs first. Inside it, Speak() is called. Because Speak() is virtual, the runtime calls Dog.Speak().

But at that moment, name has not been assigned yet by the Dog constructor. Its value is still null.

So this line fails:

Console.WriteLine(name.ToUpper());

That can cause a NullReferenceException.

Safer alternative

Use a non-virtual method in the constructor, or move overridable behavior to a method called after construction:

class Animal
{
    public Animal()
    {
        InitializeCore();
    }

    private void InitializeCore()
    {
        Console.WriteLine("Base initialization only");
    }
}

Or:

class Animal
{
    public void Initialize()
    {
        OnInitialize();
    }

    protected virtual void OnInitialize()
    {
    }
}

class Dog : Animal
{
    private string name;

    public Dog()
    {
        name = "Rex";
    }

    protected override void OnInitialize()
    {
        Console.WriteLine(name.ToUpper());
    }
}

var dog = new Dog();
dog.Initialize();

Now the object is fully constructed before the overridable method runs.

Step by Step Execution

Consider this example:

class Base
{
    public Base()
    {
        Console.WriteLine("Base constructor start");
        Show();
        Console.WriteLine("Base constructor end");
    }

    public virtual void Show()
    {
        Console.WriteLine("Base.Show");
    }
}

class Derived : Base
{
    private string message = "Hello from Derived";

    public Derived()
    {
        Console.WriteLine("Derived constructor");
    }

    public override void Show()
    {
        Console.WriteLine(message.Length);
    }
}

var obj = new Derived();

What happens step by step:

  1. Memory is allocated for a Derived object.

  2. Its fields begin with default values.

    • message is initially null
  3. The Base constructor runs first.

  4. Base prints:

    • Base constructor start
  5. Base calls Show().

  6. Because Show() is virtual, Derived.Show() runs.

  7. Derived.Show() tries to evaluate:

    message.Length
    
  8. But message is still null at this point.

  9. A NullReferenceException occurs before the Derived constructor body finishes.

The important lesson is that dynamic dispatch still happens inside constructors, but derived initialization is not complete yet.

Real World Use Cases

This issue appears in real code whenever inheritance and initialization are mixed.

Framework base classes

A base class may try to "hook" custom behavior during construction:

public abstract class ReportBase
{
    protected ReportBase()
    {
        LoadConfiguration();
    }

    protected virtual void LoadConfiguration() { }
}

A subclass override might depend on services, settings, or fields that are assigned later.

UI or game objects

A base class may call a render, setup, or registration method too early. The derived class may expect controls, textures, or state objects to already exist.

Dependency-heavy classes

If a derived class sets up dependencies in its constructor, an early virtual call can access those dependencies before they are available.

Template method misuse

The template method pattern is valid, but calling the template hook from a constructor is often unsafe unless the design guarantees no derived state is needed.

Take Quiz

Real Codebase Usage

In real projects, developers usually avoid virtual calls in constructors and use safer patterns.

1. Keep constructor logic simple

Constructors usually:

  • assign parameters to fields
  • validate required arguments
  • establish object invariants

They should avoid calling overridable behavior.

2. Use guard clauses

A constructor can safely validate inputs:

public UserService(string connectionString)
{
    if (string.IsNullOrWhiteSpace(connectionString))
        throw new ArgumentException("Connection string is required.");

    _connectionString = connectionString;
}

This is safe because it does not depend on subclass overrides.

3. Use explicit initialization methods

Sometimes construction and setup are split:

var handler = new CustomHandler();
handler.Initialize();

This gives the full object time to finish construction first.

4. Use factories

A factory can create the object and then call setup steps in the correct order.

var service = ServiceFactory.CreateConfiguredService();

5. Prefer composition over inheritance when setup is complex

Instead of relying on overridable constructor-time behavior, pass collaborators into the class.

6. Use non-virtual helper methods in constructors

If the constructor must do work, keep it internal to the current class and non-overridable.

Common Mistakes

Mistake 1: Assuming the derived constructor runs first

It does not. In C#, base constructors run before derived constructors.

Broken example:

class Base
{
    public Base()
    {
        Init();
    }

    protected virtual void Init() { }
}

class Derived : Base
{
    private string value;

    public Derived()
    {
        value = "ready";
    }

    protected override void Init()
    {
        Console.WriteLine(value.Length);
    }
}

Why it breaks:

  • Base() calls Init()
  • Derived.Init() runs
  • value is still null

Mistake 2: Thinking field initializers always save you

Even if a field has an initializer, overridden methods can still observe an object in a partially initialized state, especially when the method depends on constructor work or multiple fields being consistent.

Mistake 3: Calling virtual properties instead of methods

Properties are just methods under the hood.

Broken example:

class Base
{
    public Base()
    {
        Console.WriteLine(Name);
    }

    protected virtual string Name => "Base";
}

If a derived class overrides Name and uses not-yet-ready state, the same problem appears.

Mistake 4: Hiding the warning instead of fixing the design

Suppressing the warning may remove noise, but it does not remove the risk.

How to avoid these issues

  • avoid virtual calls in constructors
  • avoid calling overridable properties from constructors
  • move extension points to a post-construction method
  • keep constructors focused on basic setup

Comparisons

ApproachSafe during constructor?Why
Call a virtual methodNoA derived override may run before derived initialization finishes
Call a private methodYesIt cannot be overridden
Call a sealed or non-virtual methodUsually yesDispatch does not jump to subclass behavior
Use an explicit Initialize() methodYes, if called laterThe object is fully constructed first
Use a factory to create and configure objectsYesInitialization order can be controlled

Virtual vs non-virtual in constructors

Member typeCan derived behavior run?Constructor risk
private methodNoLow
non-virtual methodNoLow
virtual methodYesHigh
abstract method call through constructor pathYesHigh
virtual propertyYesHigh

The key difference is dynamic dispatch. If the member can be overridden, constructor-time calls can escape into subclass code too early.

Take Quiz

Cheat Sheet

// Risky
class Base
{
    public Base()
    {
        DoWork(); // virtual call in constructor
    }

    protected virtual void DoWork() { }
}
// Safer
class Base
{
    public Base()
    {
        DoBaseWork(); // non-virtual
    }

    private void DoBaseWork() { }
}
// Also safer: post-construction hook
class Base
{
    public void Initialize()
    {
        OnInitialize();
    }

    protected virtual void OnInitialize() { }
}

Rules to remember

  • Base constructors run before derived constructors.
  • virtual calls use runtime dispatch, even during construction.
  • An override may run before derived fields or dependencies are ready.
  • The same warning applies to virtual properties.
  • Prefer non-virtual constructor logic.
  • If customization is needed, call it after construction.

Warning signs

  • base constructor calls virtual method
  • base constructor reads overridden property
  • override depends on fields, services, or constructor parameters
  • inheritance hierarchy contains setup logic

Safe alternatives

  • private helper methods
  • explicit Initialize() methods
  • factories
  • composition instead of inheritance

FAQ

Why does C# call the derived override from the base constructor?

Because virtual dispatch is based on the actual runtime type of the object, not the class currently executing the constructor.

Is it always wrong to call a virtual method in a constructor?

Not always, but it is risky and usually a bad design choice. It is only safe if the override does not depend on derived state, which is hard to guarantee over time.

Does this problem apply to properties too?

Yes. Virtual properties are implemented through methods, so overridden getters or setters can have the same issue.

Why do tools like ReSharper warn about this?

Because it often causes subtle bugs involving partially initialized objects, null values, and fragile inheritance.

What should I do instead of calling a virtual member in a constructor?

Use non-virtual constructor logic, an explicit initialization method, a factory, or redesign the class to use composition.

Does this only matter in inheritance-heavy code?

Yes, the problem appears when a member can be overridden. If there is no inheritance or no virtual dispatch, the issue does not arise directly.

Can field initializers in the derived class prevent the problem?

Sometimes they help, but they do not make the pattern safe in general. Overrides may still depend on other state that is not ready yet.

Take Quiz

Mini Project

Description

Build a small C# example that demonstrates the problem with virtual calls in constructors and then refactor it into a safer design. This helps you see both the bug and the fix in a realistic but simple scenario.

Goal

Create a class hierarchy where a base constructor causes an early virtual call, then rewrite it so initialization happens safely after construction.

Requirements

  1. Create a base class that calls a virtual member from its constructor.
  2. Create a derived class whose override depends on a field set in the derived constructor.
  3. Show that the original version can fail or behave incorrectly.
  4. Refactor the design to avoid calling the virtual member during construction.
  5. Run the safe version after the object is fully created.
Take Quiz

Keep learning

Related questions

View more