Back to Blog
C#

C# Abstract vs Virtual: Key Differences

c# abstract vs virtual: Compare abstract and virtual methods in C#: syntax, override requirements, base calls, and when to use each for maintainable class design.

abstract methodsvirtual methodsmethod overridingpolymorphismclass design
Diagram contrasting abstract and virtual method declarations in a C# base class hierarchy

When comparing c# abstract vs virtual, the core question is whether a base class method must be overridden or merely may be overridden. An abstract method has no implementation and forces every derived class to provide one. A virtual method provides a default implementation that derived classes can replace when needed.

The Syntax Difference

public abstract class Shape { public abstract double Area(); public virtual string Describe() { return "A shape"; } }

In this example, Area() is abstract. Any non-abstract class that derives from Shape must implement Area(). The compiler enforces this at compile time. Describe() is virtual. It has a working implementation, and derived classes can override it or leave it alone.

The abstract keyword requires the method to have no body. The virtual keyword requires the method to have a body. That single difference drives everything else about how these methods behave in a hierarchy.

What Abstract Methods Enforce

An abstract method is a contract. The base class declares that the behavior exists but does not define how it works. The compiler will not allow a concrete derived class to omit the implementation.

public class Circle : Shape { public double Radius { get; set; } public override double Area() { return Math.PI * Radius * Radius; } }

If Circle did not override Area(), the code would not compile. This is the key difference: abstract methods create a compile-time obligation. Every concrete subclass must supply the behavior, which makes abstract methods a strong tool for enforcing consistency across a type hierarchy.

Abstract methods can only exist inside abstract classes. You cannot declare an abstract method in a non-abstract class because the method has no body to call. If a class contains even one abstract method, the class itself must be marked abstract.

What Virtual Methods Allow

A virtual method provides a default implementation. Derived classes may override it, but they are not required to.

public class Rectangle : Shape { public double Width { get; set; } public double Height { get; set; } public override double Area() { return Width * Height; } public override string Describe() { return "A rectangle"; } }

A derived class that does not override Describe() inherits the base implementation. This is useful when most derived types share the same behavior but a few need customization. The base implementation acts as a fallback, and the override mechanism provides the customization point.

Unlike abstract methods, virtual methods can exist in any class, abstract or not. A non-abstract class can declare a virtual method and provide a default body for it.

Override Behavior and Base Calls

When a virtual method is overridden, the derived implementation can call the base implementation using base.

public class LoggedShape : Shape { public override string Describe() { var description = base.Describe(); return $"{description} (logged)"; } }

This pattern is common when the derived class needs to extend rather than replace the base behavior. Abstract methods cannot call a base implementation because there is no base implementation to call.

The runtime dispatches virtual calls based on the actual runtime type of the object, not the declared type. This is what enables polymorphic behavior. When you hold a Shape reference that actually points to a Rectangle, calling Describe() invokes the Rectangle implementation.

Choosing Between Abstract and Virtual

Use an abstract method when every derived class must provide its own implementation and there is no sensible default. Use a virtual method when a default implementation exists and most derived classes will use it unchanged.

ConsiderationAbstractVirtual
Implementation in base classNoneRequired
Derived class must overrideYesNo
Can call base implementationNoYes
Best forContracts with no sensible defaultShared behavior with customization points

For example, a Shape base class might declare Area() as abstract because a shape without an area formula is meaningless. It might declare Describe() as virtual because "A shape" is a reasonable default that specialized shapes can refine.

The decision should be driven by whether a meaningful default exists. If the base class cannot provide a useful implementation, make the method abstract. If it can, make it virtual.

Maintainability Implications

The choice between abstract and virtual affects how the codebase evolves. Adding a new abstract method to a base class breaks every derived class at compile time. This is intentional when the method represents a fundamental capability that all derived types must have.

Adding a new virtual method does not break existing derived classes. Those classes simply inherit the default implementation. This is useful when the method is an optional extension point.

However, virtual methods carry a subtle maintenance risk. If a derived class overrides a virtual method and the base implementation changes later, the derived class may not reflect the new behavior. This is why virtual methods should be designed deliberately. In C#, methods are not virtual by default, which keeps the override surface area explicit and forces developers to opt in to extensibility.

Common Mistakes and Edge Cases

One common mistake is declaring a method abstract when a default implementation would be useful. This forces every derived class to duplicate the same logic. Another mistake is making a method virtual when it should be abstract, allowing derived classes to omit a required behavior.

A related edge case involves the sealed modifier. An override can be marked sealed to prevent further overrides in deeper derived classes.

public class SealedCircle : Circle { public sealed override double Area() { return base.Area(); } }

This stops the override chain. It is useful when the implementation must remain fixed for all further subclasses.

Another edge case: abstract methods cannot be private or sealed. Virtual methods cannot be private either, because a private method cannot be overridden. Both can be protected, which is the typical access level for override points. A protected abstract or virtual method is visible to derived classes but hidden from external callers, which keeps the extension surface internal to the hierarchy.

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