Back to Blog
C#

C# Virtual vs Abstract: When to Use Each

c# virtual vs abstract: Understand the difference between virtual and abstract members in C#, when to use each, and how they affect inheritance and polymorphism.

C#virtualabstractinheritancepolymorphismmethod overriding
Diagram showing virtual and abstract method override behavior in C# inheritance

c# virtual vs abstract requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

What Are Virtual and Abstract Members in C#?

In C#, both virtual and abstract modifiers allow derived classes to override members, but they behave differently. A virtual method has an implementation in the base class and can be optionally overridden. An abstract method has no implementation and must be overridden in a derived class if that class is not abstract.

Example:

public class Base { public virtual void Display() => Console.WriteLine("Base"); } public abstract class AbstractBase { public abstract void Draw(); }

The virtual method can be called on a base instance; the abstract method cannot be called because it has no body.

Key Differences Between Virtual and Abstract Members

The most important distinction is that abstract members require overriding, while virtual members do not. Also, abstract can only be used in abstract classes, while virtual can be used in any class. abstract members cannot have a body, virtual members must have a body. abstract members must be overridden in the first concrete derived class, whereas virtual members are overridden only if the derived class chooses to.

FeatureVirtualAbstract
Has implementationYesNo
Must be overriddenNoYes (in concrete derived class)
Allowed in non-abstract classYesNo
Can be used with properties/eventsYesYes

When to Use Virtual Methods

Use virtual when you want to provide a default implementation that derived classes can replace or extend. This is common for template methods, hooks, or extension points. For example, a Logger class might have a virtual method to format messages, allowing subclasses to customize formatting without duplicating the logging logic.

public class Logger { public virtual string Format(string message) => $"{DateTime.Now}: {message}"; } public class TimestampLogger : Logger { public override string Format(string message) => $"[{DateTime.Now:HH:mm}] {message}"; }

When to Use Abstract Methods and Classes

Use abstract when you want to define a contract that every derived class must implement, but you cannot provide a sensible default. For example, a Shape class might have an abstract Area property because each shape calculates area differently. Abstract classes are also useful for sharing common fields or methods while forcing derived classes to implement specific behavior.

public abstract class Shape { public abstract double Area { get; } public void Print() => Console.WriteLine($"Area: {Area}"); } public class Circle : Shape { public double Radius { get; set; } public override double Area => Math.PI * Radius * Radius; }

Runtime Behavior and Overriding Rules

When you call a virtual method on a base reference, the runtime uses the most derived override. If a derived class does not override, the base implementation runs. For abstract methods, the runtime always calls the override because the base has no implementation. This is a key difference in how polymorphism works.

One subtlety: you can have a virtual method that is overridden, and then further derived classes can override again. Abstract methods can also be overridden in intermediate abstract classes, but the first concrete class must implement all remaining abstract members.

Common Mistakes and How to Avoid Them

A common mistake is using virtual when you actually need abstract, leading to a base implementation that is never appropriate. Another mistake is forgetting to mark a derived class as override, which hides the base method instead of overriding it. This can cause subtle bugs because the call resolves based on the reference type, not the runtime type.

For example:

public class Derived : Base { public void Display() => Console.WriteLine("Derived"); // hides, not overrides }

If you call Base b = new Derived(); b.Display(); it prints "Base" because the method is hidden, not overridden. Use override to get polymorphic behavior.

Practical Example: Combining Virtual and Abstract

A common pattern is to have an abstract base class that defines an abstract method for the core operation, and virtual methods for optional hooks. Consider a data processor:

public abstract class DataProcessor { public void Process() { var data = LoadData(); var result = Transform(data); Save(result); } protected abstract string LoadData(); protected virtual string Transform(string data) => data.ToUpper(); protected abstract void Save(string result); }

Here, LoadData and Save must be implemented, but Transform can be overridden if needed. This gives a clear contract with flexibility.

Choosing Between Virtual and Abstract in Your Design

The decision comes down to whether a sensible default implementation exists. If yes, use virtual. If no, use abstract. Also, if you need to force all derived classes to implement a member, use abstract. If you want to allow but not require overriding, use virtual. In inheritance hierarchies, abstract classes often serve as base contracts, while virtual methods provide extension points.

c# virtual vs abstract: Practical Usage and Code Examples | RYUSLOG DEV