Skip to content
Theory · Inheritance and interfaces · lesson 4 of 10

Method hiding: new

In the previous lesson, a derived class rewrote a method that the base class had marked with the word virtual. What happens if there is no virtual, yet the derived class declares a method with the same name and the same parameters?

Picture a fleet with the instruction "how to say who you are" on the shared board, and nobody may rewrite it. The car drivers put a leaflet with the same title into their own folder. Whoever looks for the instruction on the shared board reads the shared one. Whoever opens the cars' folder reads the leaflet. What gets read depends on where you looked.

C#
Car car = new Car();
Vehicle v = car;
Console.WriteLine(car.Who()); // car
Console.WriteLine(v.Who());   // vehicle

class Vehicle
{
    public string Who() => "vehicle";
}

class Car : Vehicle
{
    public new string Who() => "car";
}

Let's walk through it line by line:

  1. Car car = new Car(); creates one Car object.
  2. Vehicle v = car; gives the same object a second name: the variable v of type Vehicle.
  3. car.Who() looks for the method in the type Car and finds its own version there: it prints car.
  4. v.Who() looks for the method in the type Vehicle and finds the base version: it prints vehicle.

One and the same object answered in two ways, because the variable's type picked the version.

Hiding and the new modifier

The method Who in Car does not override the method of Vehicle; it hides it. Hiding is declaring a method in a derived class with the same name and the same parameters as a method of the base class, without override. The base method has not gone anywhere: any code that sees the object through the type Vehicle calls it. A method with the same name but other parameters hides nothing: it is an overload.

The new modifier in the declaration public new string Who() tells the compiler the hiding is intended. Remove new, and the program still compiles and prints the same, but with a warning:

TEXT
warning CS0108: 'Car.Who()' hides inherited member 'Vehicle.Who()'. Use the new keyword if hiding was intended.

The compiler suspects that the same name turned up by accident. new clears that suspicion and changes nothing else. Do not confuse this modifier with new in the expression new Car(): the word is the same, but the meaning differs.

Here the board analogy is off. In the fleet, the reader decides where to look. In a program, the compiler makes the choice before the program runs, and it looks only at the variable's type.

override or new

How does override differ from new? This is a classic interview question. Let's look at both modifiers in one program:

C#
Vehicle truck = new Truck();
Bike bike = new Bike();
Vehicle b = bike;
Console.WriteLine(truck.Who()); // truck
Console.WriteLine(b.Who());     // vehicle
Console.WriteLine(bike.Who());  // bike

class Vehicle
{
    public virtual string Who() => "vehicle";
}

class Truck : Vehicle { public override string Who() => "truck"; }

class Bike : Vehicle { public new string Who() => "bike"; }

Let's go through the three calls:

  1. truck.Who() prints truck: Truck overrode the virtual method, and the object picks the version.
  2. b.Who() prints vehicle: Bike hid the method, so through a variable of type Vehicle the base version runs.
  3. bike.Who() prints bike: the variable has type Bike, and the version from Bike is visible.

Here is the difference in a table:

overridenew
What the base method needsvirtualnothing
What picks the versionthe object's type, at run timethe variable's type, at compile time
A call through a base-type variablethe derived class's versionthe base class's version

Methods are usually overridden, and hiding is rare. Accidental hiding, however, is a common mistake.

Common mistake

While overriding ToString, someone forgot to write override:

C#
var bike = new Bike();
Console.WriteLine(bike); // Bike

class Bike
{
    public string ToString() => "my bike"; // ✗
}
TEXT
warning CS0114: 'Bike.ToString()' hides inherited member 'object.ToString()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.

The program compiles and prints Bike, not my bike. Without override, the method ToString in Bike hid the virtual ToString of object instead of overriding it. Console.WriteLine takes the object as an object and so calls the version of object, which returns the type's name. Write public override string ToString(), and the program prints my bike.

Key points

  • A method with the same name and parameters but no override hides the base class's method; the new modifier says this is intended and removes the warning CS0108.
  • With hiding, the variable's type picks the version; with overriding, the object's type does.
  • A method declared with new is not visible through a base-type variable: the base class's version runs.
  • A forgotten override turns overriding into hiding, and the compiler warns with CS0114.