Back to Blog
C#

C# New Method Hiding: Syntax and Runtime Behavior

Understand C# method hiding with the new modifier: syntax, runtime dispatch behavior, differences from overriding, and when hiding is a deliberate design choice.

C#method hidinginheritancepolymorphismnew modifier
Diagram showing a base class method being hidden by a derived class method with the new modifier in C#

C# new method hiding is the mechanism by which a derived class declares a member with the same name and signature as a base-class member without overriding it. The new modifier makes that intent explicit, and the compiler treats the two declarations as separate members. Understanding this behavior matters because it changes how calls are resolved at runtime and can silently alter program behavior depending on the declared type of a variable.

What Method Hiding Does in C#

When a derived class declares a member with the same name and signature as a base-class member without overriding it, the derived member hides it. The new modifier suppresses the compiler warning and documents that the hiding is deliberate.

public class BaseClass { public void Display() { Console.WriteLine("Base display"); } } public class DerivedClass : BaseClass { public new void Display() { Console.WriteLine("Derived display"); } }

Calling Display through a DerivedClass reference executes the derived implementation. Calling it through a BaseClass reference executes the base implementation. The method is not virtual, so the runtime does not consider the actual object type when selecting which method to invoke.

How Hiding Differs from Overriding

Overriding requires a virtual method in the base class and an override modifier in the derived class. The runtime then uses the actual object type to select the implementation, regardless of the static type of the reference.

public class BaseClass { public virtual void Display() { Console.WriteLine("Base display"); } } public class DerivedClass : BaseClass { public override void Display() { Console.WriteLine("Derived display"); } }

With overriding, both a BaseClass reference and a DerivedClass reference produce the derived output when the object is actually a DerivedClass. With hiding, the static type of the reference determines which method runs. That distinction is the core difference between the two mechanisms.

Runtime Behavior: Static Dispatch and Call Sites

For a hidden non-virtual method, calls use static dispatch. The compiler resolves the call at compile time based on the declared type of the variable, not the runtime type of the object. This has a direct consequence: hiding a method changes behavior depending on how the object is referenced.

BaseClass b = new DerivedClass(); b.Display(); // "Base display" DerivedClass d = new DerivedClass(); d.Display(); // "Derived display"

This asymmetry is the main source of confusion. If a method is hidden, code that receives the object through a base-class reference continues to call the base implementation. That can be intentional, but it also means the derived behavior is not consistently applied across all call sites.

Why the CS0108 Warning Matters

If the inherited member is not virtual, the compiler emits warning CS0108 when a derived member hides it without the new modifier. If the base member is virtual and the derived member declares the same signature without override or new, the compiler emits CS0114 instead. The warning is not an error, but it signals a likely mistake: the developer probably intended to override but the base method was not marked virtual, or the derived method was not marked override.

public class DerivedClass : BaseClass { public void Display() // CS0108 warning { Console.WriteLine("Derived display"); } }

Adding new suppresses the warning and documents the intent. Changing the base method to virtual and using override instead changes the runtime behavior, so the decision should be deliberate rather than a reflex to silence the compiler.

When Method Hiding Is Useful

Method hiding is appropriate when you want to provide a different implementation for callers who use the derived type directly while preserving the base behavior for callers who use the base type. This is uncommon in application code but can appear in framework scenarios where you cannot modify the base class.

A common pattern is hiding a method to return a more specific type:

public class Repository { public object GetData() => LoadFromDatabase(); } public class UserRepository : Repository { public new User GetData() => LoadUser(); }

Callers who know they have a UserRepository get the typed result without a cast. Callers who only have a Repository still get the base behavior. This works because the call-site type controls which method is selected, so each call binds to the method matching its declared type.

Maintainability and Compatibility Concerns

Method hiding introduces a maintenance burden because the behavior of a call depends on the static type of the reference. If a developer changes a variable's declared type from DerivedClass to BaseClass, the behavior silently changes. This makes code harder to reason about than virtual dispatch, where the actual object type consistently determines behavior.

Hiding also creates a compatibility trap when the base class later adds a member with the same signature. The derived class's new member then hides a member the base author may not have anticipated, and callers through the base type get the base implementation even when the object is derived. This can produce subtle bugs that only surface when a third-party library is upgraded.

When you control the base class, prefer virtual and override for polymorphic behavior. Reserve new for cases where you intentionally want type-dependent behavior and you are certain callers will use the derived type directly.

Edge Cases: Hiding Virtual Members and Interface Members

You can hide a virtual member with new. The member declared with new is not virtual, so it does not participate in the base method's virtual dispatch. Calls through a base reference still dispatch virtually to the original virtual method, but calls through the derived type reference invoke the new non-virtual member.

public class BaseClass { public virtual void Display() { } } public class DerivedClass : BaseClass { public new void Display() { } } public class FurtherDerived : DerivedClass { public override void Display() { } // error: no virtual member to override }

This combination splits the hierarchy into two parallel method sets and makes further inheritance confusing. A class further down the hierarchy cannot override the hidden member because it is no longer virtual. If you find yourself hiding a virtual member, reconsider whether overriding is the correct approach.

Interface members can also be hidden. When a class implements an interface implicitly and a derived class hides the implementing member, interface calls through the interface reference continue to dispatch to the member that implemented the interface, unless the derived class re-implements the interface and changes the mapping. This is another case where the call-site type can determine behavior, and it can surprise developers who expect interface dispatch to follow the object's runtime type.

C# New Method Hiding: Syntax, Runtime Behavior, and Practical Examples | RYUSLOG DEV