C# Inheritance: Virtual, Override, New, and Hidden Dangers
C# inheritance is quite easy to implement but sometimes complex to understand. Sure, most developers know what virtual, override, and new do. But what if we throw in a couple of casts and a few extra levels of inheritance? Now things aren’t so straightforward. This article assumes you already know what inheritance is. Initial Setup: internal class Animal { public virtual void sound() { Console.WriteLine("Animal makes noise"); } public virtual void move() { Console.WriteLine("Animal moved"); } } internal class Dog : Animal { public override void sound() { Console.WriteLine("Dog barks"); } public virtual new void move() { Console.WriteLine("Dog runs"); } } internal class SuperDog : Dog { public override void sound() { Console.WriteLine("Super Dog howls"); } public override void move() { Console.WriteLine("Super Dog sprints"); } } internal class Duck : Animal { public new void sound() { Console.WriteLine("Duck quacks"); } public override void move() { Console.WriteLine("Duck Duck go!"); } } ❓ Question 1: What is the output? Animal al = new Animal(); al.sound(); al.move(); Animal d1 = new Dog(); d1.sound(); d1.move(); Animal d2 = new SuperDog(); d2.sound(); d2.move(); Dog sd = new SuperDog(); sd.sound(); sd.move(); Animal dk = new Duck(); dk.sound(); dk.move(); ❓ Question 2: What does virtual new mean? Does it still hide the base implementation? Does it still declare the method for further override? ❓ Question 3: Guess the output! Update the Dog class like this: internal class Dog : Animal { public override void sound() { base.sound(); Console.WriteLine("Dog barks"); } public virtual new void move() { base.move(); Console.WriteLine("Dog runs"); } } Now what do you think this will print? Dog d3 = new Dog(); d3.sound(); d3.move(); Constructors and Virtual Methods Constructors are meant to initialize the class state before it can be used. public class Base { public Base() { Console.WriteLine("Base constructor"); Init(); } public virtual void Init() { Console.WriteLine("Init Called: Base class"); // Base logic (maybe logging or setup) } } public class Derived : Base { private List _logMessages; private string _message = "Initialization starts"; public Derived() { _logMessages = new List(); } public override void Init() { Console.WriteLine(_message); _logMessages.Add("Init Called: Derived class"); } } ❓ Question 4: Answer the following: Does the above code run properly? What does the output look like? ✅ Solutions: Question 1: Animal al = new Animal(); al.sound(); // Animal makes noise al.move(); // Animal moved Animal d1 = new Dog(); d1.sound(); // Dog barks d1.move(); // Animal moved Animal d2 = new SuperDog(); d2.sound(); // Super Dog howls d2.move(); // Animal moved Dog sd = new SuperDog(); sd.sound(); // Super Dog howls sd.move(); // Super Dog sprints Animal dk = new Duck(); dk.sound(); // Animal makes noise dk.move(); // Duck Duck go! Question 2: virtual new declares a method that: Hides the current base class implementation, and Allows the method to be overridden in future derived classes. So yes, it hides the base method for the current class and opens it for further overriding. Question 3: If a method exists in the base class and is accessible (not private), base.MethodName() will work inside the derived class—whether it's overridden or hidden using new. Output: Animal makes noise Dog barks Animal moved Dog runs Question 4: Does the above code run normally? Hell no! Why? Assume we create an object like this: Derived dd = new Derived(); What really happens: CLR starts memory allocation for the object. Field _message is declared and initialized. Field _logMessages is declared, but not yet initialized. The base class constructor is invoked (derived constructor hasn't run yet). Inside the base constructor, Init() is called. Because it's virtual, it dispatches to Derived.Init(). In Derived.Init(), _logMessages.Add(...) is called—but _logMessages is null!

C# inheritance is quite easy to implement but sometimes complex to understand.
Sure, most developers know what virtual
, override
, and new
do. But what if we throw in a couple of casts and a few extra levels of inheritance? Now things aren’t so straightforward.
This article assumes you already know what inheritance is.
Initial Setup:
internal class Animal
{
public virtual void sound()
{
Console.WriteLine("Animal makes noise");
}
public virtual void move()
{
Console.WriteLine("Animal moved");
}
}
internal class Dog : Animal
{
public override void sound()
{
Console.WriteLine("Dog barks");
}
public virtual new void move()
{
Console.WriteLine("Dog runs");
}
}
internal class SuperDog : Dog
{
public override void sound()
{
Console.WriteLine("Super Dog howls");
}
public override void move()
{
Console.WriteLine("Super Dog sprints");
}
}
internal class Duck : Animal
{
public new void sound()
{
Console.WriteLine("Duck quacks");
}
public override void move()
{
Console.WriteLine("Duck Duck go!");
}
}
❓ Question 1: What is the output?
Animal al = new Animal();
al.sound();
al.move();
Animal d1 = new Dog();
d1.sound();
d1.move();
Animal d2 = new SuperDog();
d2.sound();
d2.move();
Dog sd = new SuperDog();
sd.sound();
sd.move();
Animal dk = new Duck();
dk.sound();
dk.move();
❓ Question 2: What does virtual new
mean?
- Does it still hide the base implementation?
- Does it still declare the method for further override?
❓ Question 3: Guess the output!
Update the Dog
class like this:
internal class Dog : Animal
{
public override void sound()
{
base.sound();
Console.WriteLine("Dog barks");
}
public virtual new void move()
{
base.move();
Console.WriteLine("Dog runs");
}
}
Now what do you think this will print?
Dog d3 = new Dog();
d3.sound();
d3.move();
Constructors and Virtual Methods
Constructors are meant to initialize the class state before it can be used.
public class Base
{
public Base()
{
Console.WriteLine("Base constructor");
Init();
}
public virtual void Init()
{
Console.WriteLine("Init Called: Base class");
// Base logic (maybe logging or setup)
}
}
public class Derived : Base
{
private List<string> _logMessages;
private string _message = "Initialization starts";
public Derived()
{
_logMessages = new List<string>();
}
public override void Init()
{
Console.WriteLine(_message);
_logMessages.Add("Init Called: Derived class");
}
}
❓ Question 4: Answer the following:
- Does the above code run properly?
- What does the output look like?
✅ Solutions:
Question 1:
Animal al = new Animal();
al.sound(); // Animal makes noise
al.move(); // Animal moved
Animal d1 = new Dog();
d1.sound(); // Dog barks
d1.move(); // Animal moved
Animal d2 = new SuperDog();
d2.sound(); // Super Dog howls
d2.move(); // Animal moved
Dog sd = new SuperDog();
sd.sound(); // Super Dog howls
sd.move(); // Super Dog sprints
Animal dk = new Duck();
dk.sound(); // Animal makes noise
dk.move(); // Duck Duck go!
Question 2:
virtual new
declares a method that:
- Hides the current base class implementation, and
- Allows the method to be overridden in future derived classes.
So yes, it hides the base method for the current class and opens it for further overriding.
Question 3:
If a method exists in the base class and is accessible (not private
), base.MethodName()
will work inside the derived class—whether it's overridden or hidden using new
.
Output:
Animal makes noise
Dog barks
Animal moved
Dog runs
Question 4:
Does the above code run normally?
Hell no!
Why?
Assume we create an object like this:
Derived dd = new Derived();
What really happens:
- CLR starts memory allocation for the object.
- Field
_message
is declared and initialized. - Field
_logMessages
is declared, but not yet initialized. - The base class constructor is invoked (derived constructor hasn't run yet).
- Inside the base constructor,
Init()
is called. - Because it's virtual, it dispatches to
Derived.Init()
. - In
Derived.Init()
,_logMessages.Add(...)
is called—but_logMessages
is null!