What is the difference between virtual, override and new (method hiding)?
Quick Answer
virtual marks a base method as overridable. override in a derived class replaces it — calls are dispatched to the derived version even through a base-type reference (true polymorphism). new hides the base method instead: which method runs depends on the compile-time type of the reference, not the actual object.
virtual says “this method can be overridden”. override in a subclass actually replaces it, and the important part is that the call is resolved at runtime based on the real object — so a base-class reference pointing at a derived object still calls the derived method. new is method hiding: it looks similar, but the method that runs is chosen by the compile-time type of the variable, not the object. So if I have an Animal variable holding a Dog, override gives me Dog's behaviour and new gives me Animal's. new is almost always a mistake — I'd use virtual/override.
Given Animal a = new Dog();:
- If
Speak()isvirtualinAnimalandoverrideinDog, thena.Speak()runsDog.Speak()— the runtime looks at the real object. - If
Dogdeclaresnew void Speak(), thena.Speak()runsAnimal.Speak()(reference is typedAnimal), but((Dog)a).Speak()runsDog.Speak().
new just silences the compiler warning about hiding; it does not participate in polymorphism and is usually a design smell. Prefer virtual/override. Related keywords: abstract (virtual with no body, must override), sealed override (override but block further overriding), base.Method() (call the base implementation from the override).
class Animal { public virtual string Speak() => "..."; }
class Dog : Animal { public override string Speak() => "Woof"; }
class Cat : Animal { public new string Speak() => "Meow"; } // hides
Animal d = new Dog();
Animal c = new Cat();
d.Speak(); // "Woof" — polymorphic
c.Speak(); // "..." — base version! (reference is Animal)
((Cat)c).Speak(); // "Meow"