C# Virtual, Override, and New Keywords Explained
In C#, method inheritance and polymorphism rely heavily on three
fundamental keywords: virtual, override, and
new. Understanding how these keywords interact is essential
for managing method execution when working with base classes and derived
types. This article breaks down the purpose of each keyword, explains
the crucial distinction between runtime polymorphism and method hiding,
and provides clear code examples to show how they behave in
practice.
The virtual Keyword
The virtual keyword is applied to a method, property, or
event in a base class to declare that its implementation can be altered
by a derived class.
- Default Implementation: Unlike
abstractmethods, avirtualmethod must provide a default implementation in the base class. - Opt-in Polymorphism: It acts as an open invitation to subclasses to customize the behavior using late binding.
- Rule: A
virtualmethod cannot be marked asstatic,abstract, orprivate.
The override Keyword
The override keyword is used in a derived class to
replace an inherited member that was declared as virtual or
abstract.
- Runtime Polymorphism: When a method is overridden, the runtime determines which version of the method to execute based on the actual type of the object in memory, not the type of the reference variable pointing to it.
- Preserving Signatures: The signature, return type,
and access modifiers of the
overridemethod must match the original base member.
The new Keyword
When used as a method modifier, the new keyword
explicitly hides an inherited member from a base class. This concept is
often referred to as method shadowing or method
hiding.
- No Polymorphism: The
newkeyword breaks the polymorphic chain. It does not replace the base method; instead, it introduces an entirely separate method that happens to share the same name and signature. - Compile-Time Binding: The method called is determined by the compile-time type of the reference, not the actual object type at runtime.
- Suppression of Warnings: If you define a method in
a derived class with the same name as a base method without using
overrideornew, the C# compiler generates a warning. Adding thenewkeyword suppresses this warning, confirming the hiding is intentional.
Summary of Differences
| Feature | virtual |
override |
new |
|---|---|---|---|
| Location | Base class | Derived class | Derived class |
| Purpose | Enables overriding | Extends/replaces base logic | Hides base logic |
| Binding Type | Dynamic (Late) | Dynamic (Late) | Static (Early) |
| Polymorphic | Yes | Yes | No |
Code Example
The distinction between override and new
becomes immediately apparent when an instance of a derived class is held
in a base class reference variable:
using System;
public class BaseClass
{
public virtual void ShowMessage()
{
Console.WriteLine("BaseClass implementation");
}
}
public class OverrideClass : BaseClass
{
public override void ShowMessage()
{
Console.WriteLine("OverrideClass implementation");
}
}
public class NewClass : BaseClass
{
public new void ShowMessage()
{
Console.WriteLine("NewClass implementation");
}
}
class Program
{
static void Main()
{
// 1. Calling via BaseClass reference
BaseClass obj1 = new OverrideClass();
BaseClass obj2 = new NewClass();
obj1.ShowMessage(); // Output: OverrideClass implementation
obj2.ShowMessage(); // Output: BaseClass implementation
// 2. Calling via Derived type reference
NewClass obj3 = new NewClass();
obj3.ShowMessage(); // Output: NewClass implementation
}
}In this example, calling ShowMessage() on
obj1 invokes the method from OverrideClass
because the method was overridden using dynamic dispatch. In contrast,
calling ShowMessage() on obj2 invokes the
method from BaseClass because NewClass merely
hid the method, causing the call to resolve to the base implementation
based on the variable's declared type.