Updated on
Method overriding is a derived class replacing a method it inherited. The base class marks the method virtual or abstract to permit it, the derived class marks its own version override, and from then on the object decides which implementation runs, not the variable holding it.
That last part is what makes overriding run-time polymorphism, and it is also the entire difference between override and the new keyword, which looks the same in the editor and behaves the opposite way.
Let’s begin.
What Is Method Overriding?
Method overriding is a derived class replacing the implementation of a method it inherited, while keeping that method’s name, parameter list, and return type.
Two keywords do the work. The base class marks the method virtual or abstract, which is C#’s way of saying a derived class may replace this. The derived class marks its version override, which is C#’s way of saying this is the replacement.
The replacement is then chosen from the object, at run time, and not from the variable. Hold a Circle in a variable of type Shape, call Draw(), and the Circle version runs, because the object is a Circle. That is why overriding is called run-time polymorphism.
None of this happens by accident. A method is not overridable unless the base class says so, and a derived method replaces nothing unless it says override. Get either half wrong and the compiler stops us or warns us, which is the subject of the rules section further down.
When Do We Need to Override a Method?
When the derived class needs to provide a specialized implementation of a method present in the base class, we need to override the method.
We may need method overriding when:
- The base class has a method whose default behaviour is wrong for one derived class
- Several subclasses need the same operation to mean something different, and the calling code should not have to know which one it is holding
- The base class is abstract and the method has no implementation to inherit, so a concrete class has to supply one
- We are overriding something the framework declared
virtualfor us:ToString()so an object prints usefully, orEquals()andGetHashCode()so two instances compare by value instead of by reference
How Do We Override a Method in C#?
Overriding takes two declarations, one in each class, and both are required.
In the base class, mark the method virtual if it has a sensible default that a derived class may want to replace, or abstract if it has no body at all and every concrete derived class must supply one. Either modifier puts the method into the set that derived classes are allowed to replace.
In the derived class, declare a method with the same name, the same parameter list, the same return type, and the same access modifier, then put override in front of it.
The override keyword is not decoration. Leave it off and the compiler treats our method as a brand new one that happens to share a name, so calls made through a base-class reference keep running the base version.
A method that is itself an override can be overridden again further down, which is how a three-level hierarchy keeps refining one behaviour.
Override a Virtual Method
Let’s start by creating a base class to understand this:
public class Shape
{
public required string Color { get; set; }
public virtual string Draw()
{
return $"Drawing a {Color} colored shape";
}
}
Here, we have a base class Shape that has a Color property and a Draw() method. The Draw() method is virtual, which means we can override it in a derived class. We cover the virtual keyword, and how the runtime picks the implementation in a separate article.
Now, let’s create a class Circle derived from Shape:
public class Circle : Shape
{
public double Radius { get; set; }
public override string Draw()
{
return $"Drawing a {Color} colored circle with a radius of {Radius} units.";
}
}
And another derived class Square:
public class Square : Shape
{
public int Side { get; set; }
public override string Draw()
{
return $"Drawing a square of color {Color} " +
$"with its sides having length and width of {Side} units";
}
}
Both classes are derived from the Shape class and both override the Draw() method to provide their own implementation.
The Draw() method in the Circle class returns a message that includes the circle’s color and radius, while the Draw() method in the Square class returns a message that includes the square’s color and side length.
Let’s create the instances of these classes and look at the overridden implementation:
var shape = new Shape { Color = "Blue" };
Console.WriteLine(shape.Draw());
var circle = new Circle { Color = "Red", Radius = 10.5 };
Console.WriteLine(circle.Draw());
var square = new Square { Color = "Green", Side = 5 };
Console.WriteLine(square.Draw());
When we create the instance of Shape class, the base implementation of the Draw() method will be called.
Whereas, the Draw() method is overridden in the Circle and Square class. Hence, the system calls the method implementation in the derived class instead of the base class’s implementation:
Drawing a Blue colored shape Drawing a Red colored circle with a radius of 10.5 units. Drawing a square of color Green with its sides having length and width of 5 units
One important thing to understand here is that it is not necessary to override a virtual method. If the derived class does not contain an overridden implementation, the instance of the derived class points to the base class implementation of the method.
So, we understood method overriding when the base class method is marked as virtual. Let’s now look at how it differs from overriding an abstract method.
Override an Abstract Method
The main difference here compared to overriding a virtual method is that an abstract method does not have an implementation of its own. Hence, we must override it in the derived class.
Let’s modify our existing example to understand this:
public abstract class Shape
{
public required string Color { get; set; }
public abstract string Draw();
}
Here, the Draw() method is not implemented in the base class and is marked as abstract which means it must be overridden by any derived class. Also, we mark the Shape class as abstract.
The Circle and Square classes continue to be derived from the Shape class and override the Draw() method to provide their own implementation.
As the Shape class is now an abstract class, we cannot create an instance of it. So, we need to create an instance of Circle or Square classes and call the Draw() method on it:
var circle = new Circle { Color = "Red", Radius = 5.5 };
Console.WriteLine(circle.Draw());
var square = new Square { Color = "Blue", Side = 12 };
Console.WriteLine(square.Draw());
The output remains similar:
Drawing a Red colored circle with a radius of 5.5 units. Drawing a square of color Blue with its sides having length and width of 12 units
Another important point to understand here is that if a derived class does not override the abstract method, we must mark it as abstract and the process repeats until we reach a class that implements the method.
Choosing between the two is a separate question: when to make a base method virtual and when to make it abstract comes down to whether there is a default worth inheriting.
What Are the Rules for Overriding a Method in C#?
C# checks five things about an override method, and each one is a compile error rather than a surprise at run time.
The base member has to be virtual, abstract, or itself an override. Ordinary methods are closed to overriding by default, and static methods cannot be overridden at all.
The signature has to match: the same name, and the same parameter types in the same order. A different parameter list is not an override, it is a separate method that happens to share a name.
The access modifier has to match as well, so a public base method cannot be overridden as protected.
The return type has to match, or be derived from the base method’s return type. C# 9 added those covariant return types, so a base method returning Shape may be overridden by one returning Circle.
And an abstract member has to be overridden by the first concrete class beneath it, because there is nothing to fall back on.
| The rule | If you break it | Message |
|---|---|---|
The base member must be virtual, abstract, or itself an override | CS0506 | cannot override inherited member ... because it is not marked virtual, abstract, or override |
| The signature must match the base method | CS0115 | no suitable method found to override |
| The access modifier must match the base method | CS0507 | cannot change access modifiers when overriding 'public' inherited member ... |
| The return type must match, or derive from, the base return type | CS0508 | return type must be 'string' to match overridden member ... |
A sealed override cannot be overridden again | CS0239 | cannot override inherited member ... because it is sealed |
An abstract member must be overridden by the first concrete class | CS0534 | ... does not implement inherited abstract member ... |
A static member cannot be overridden | CS0112 | A static member cannot be marked as 'override' |
A virtual or abstract member cannot be private | CS0621 | virtual or abstract members cannot be private |
Same name and signature, but neither override nor new | CS0114 (warning) | ... hides inherited member ... To make the current member override that implementation, add the override keyword. Otherwise add the new keyword. |
The one modifier that is not in the table is sealed: writing sealed override keeps our implementation but closes the method to anything below us, which is the method-level version of sealing a whole class.
A static method is not part of this at all: it belongs to the type rather than to any object, so there is no object for the runtime to dispatch on. Static versus non-static methods covers the difference in full.
How Do We Call the Base Class Method From an Override?
It’s common to override methods in a derived class to provide a specific implementation for that class. However, sometimes the derived class may also want to execute the original implementation of the method in the superclass.
C# provides a way to do this using the base keyword.
Let’s extend our example and create another class derived from Shape:
public class Cube : Shape
{
public int Edge { get; set; }
public override string Draw()
{
var builder = new StringBuilder();
builder.AppendLine(base.Draw());
builder.AppendLine($"Drawing a cube with edges of length, width, and height of {Edge} units");
return builder.ToString();
}
}
Now, the Draw() method in the Cube class first calls the base class’s method using the base keyword and then returns a message that includes the cube’s edge length.
If we create an instance of the Cube class and call the Draw() method:
var cube = new Cube { Color = "Yellow", Edge = 7 };
Console.WriteLine(cube.Draw());
We call the overridden implementation in the derived class along with the base class method:
Drawing a Yellow colored shape Drawing a cube with edges of length, width, and height of 7 units
The base keyword can be useful in situations where the derived class wants to extend the functionality of the base class method, rather than completely replacing it.
What Is the Difference Between override and new in C#?
Both keywords put a method in a derived class that shares a base method’s name. They differ in which one actually runs.
An override method replaces the base implementation. Whatever type the reference is declared as, the object’s version runs.
A new method hides the base implementation instead of replacing it. The compiler picks the method from the type of the reference, not from the object. Through a Sketch variable we get Sketch.Draw(). Through a Shape variable holding that same Sketch object we get Shape.Draw().
That is the whole difference: override binds to the object, new binds to the reference.
Leaving both keywords off is the third case, and it is the one to avoid. The compiler warns and then behaves as if we had written new, so the code builds, runs, and quietly does the wrong thing every time somebody calls it through a base-class variable.
Let’s add one more class to the same Shape hierarchy we have been using since the first code block:
public class Sketch : Shape
{
public new string Draw()
{
return $"Sketching a {Color} outline";
}
}
Sketch derives from Shape exactly as Circle and Square do, but its Draw() says new instead of override. Now the same object answers to two different methods depending on how we are holding it:
var sketch = new Sketch { Color = "Black" };
Console.WriteLine(sketch.Draw());
Shape sketchAsShape = sketch;
Console.WriteLine(sketchAsShape.Draw());
There is one Sketch object here and two references to it, and they do not agree:
Sketching a Black outline Drawing a Black colored shape

Hiding is not a mistake in itself. It exists so that a base class in somebody else’s library can grow a method with a name we already used without breaking our build: our method keeps working for our own callers, and new is how we tell the compiler we meant it. What is a mistake is reaching for new to “override” a method that the base class never marked virtual, because the moment our object is passed to code that holds it as the base type, our version stops running.
Microsoft’s own documentation puts the fallback behaviour plainly: if neither keyword is specified, “the compiler will issue a warning and the method in the derived class will hide the method in the base class”.
Method Overriding vs Method Overloading in C#
Both method overriding and method overloading are forms of polymorphism in C# that allow a class to have multiple methods with the same name, but with different behaviors.
With method overriding, the derived class provides a specific implementation of a method that the base class already defines. Thus, the subclass gives its own behavior to the method while maintaining the same method signature as the base class.
Whereas with method overloading, we have a class having multiple methods with the same name but different parameter lists. This allows the class to provide different behaviors for the same method based on the parameters passed in.
The two features do meet in one place worth knowing about. When a derived class declares both an override of a base method and an overload of it, the compiler prefers the overload it can see declared on the derived class, even when the overridden version is the better fit for our argument, and casting the instance to the base type is what forces the overridden version to be chosen.
Conclusion
Method overriding is one keyword in each of two classes: virtual or abstract in the base, override in the derived one. Once both are in place the object decides which implementation runs, so code holding a Shape gets the Circle behaviour without knowing it is holding a circle.
The compiler is strict about the rest, and the rules table above pairs each requirement with the error it produces. The one case it cannot catch for us is new: it compiles, it runs, and it binds to the reference instead of the object, so reach for it only when we actually mean to hide something.
Tested with .NET 10.0.10.
