-2

I am trying to understand new virtual method.

What are the differences between the following two ways:

  • define a method in a base class without virtual, and define a method with the same name and signature in a subclass

  • define a method in a base class with virtual, and define a method with the same name and signature and new in a subclass?

If they differ, why in the following example do they behave the same?

using System;

public class Base
{
    public void DoIt()
    {
      Console.WriteLine ("Base: DoIt");
    }

    public virtual void DoItVirtual1()
    {
      Console.WriteLine ("Base: DoItVirtual1");
    }

    public virtual void DoItVirtual2()
    {
      Console.WriteLine ("Base: DoItVirtual2");
    }    

}

public class Derived : Base
{
    public void DoIt()
    {
      Console.WriteLine ("Derived: DoIt");
    }
    public override void DoItVirtual1()
    {
      Console.WriteLine ("Derived: DoItVirtual1");
    }
    public new void DoItVirtual2()
    {
      Console.WriteLine ("Derived: DoItVirtual2");
    }        
}

class MainClass {
  public static void Main (string[] args) {
    Base b = new Base();
    Derived d = new Derived();
    Base bd = new Derived();

    b.DoIt(); 
    d.DoIt(); 
    bd.DoIt();

    b.DoItVirtual1();
    d.DoItVirtual1();
    bd.DoItVirtual1();

    b.DoItVirtual2();
    d.DoItVirtual2();
    bd.DoItVirtual2();
  }
}

Output:

Base: DoIt
Derived: DoIt
Base: DoIt
Base: DoItVirtual1
Derived: DoItVirtual1
Derived: DoItVirtual1
Base: DoItVirtual2
Derived: DoItVirtual2
Base: DoItVirtual2
glennsl
  • 28,186
  • 12
  • 57
  • 75
Tim
  • 1
  • 141
  • 372
  • 590
  • 3
    Possible duplicate of [Difference between new and override](https://stackoverflow.com/questions/1399127/difference-between-new-and-override) – CodingYoshi Jul 07 '19 at 16:33

3 Answers3

2

The new modifier results in the same functionality as if you were to remove it, but suppresses the compiler warning about unintentionally hiding the base class method.

By using new, you are asserting that you are aware that the member that it modifies hides a member that is inherited from the base class.

The virtual keyword has nothing to do with the new modifier here. It is only meant to allow you to override the method in the derived class.

More information here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/knowing-when-to-use-override-and-new-keywords

Matthew Coats
  • 121
  • 1
  • 3
  • do you mean `new` can be used to redefine a base method in the same way, regardless of whether the base method is qualified with or without `virtual`? – Tim Jul 07 '19 at 16:20
  • No. There are important differences between `new` and `override`. `Override` enables polymorphism, and `new` does not. When using `override`, the method that is called is always of the run-time type. When using `new`, in order for the derived method to be called, the static type (or compiler-time type) must be the derived class. In other words, if you have `BaseClass obj = new DerivedClass();` and then call `obj.DoItVirtual2()` then it will execute the BaseClass method. If you have `DerivedClass obj = new DerivedClass();` and do the same, it will run the DerivedClass method. – Matthew Coats Jul 07 '19 at 16:30
  • You don't 'redefine' base method. You just intentionally 'hide' base method with new definition in derived class. – Jacek Jul 07 '19 at 16:30
  • Sorry, I may have misunderstood your question. `New` can be used regardless of `virtual`, yes. But it's not the same as using `override`. As @Jacek said, it's hiding the base method, not redefining it. – Matthew Coats Jul 07 '19 at 16:30
  • some of us wonder why the language designers chose to include `new` as using it most of the time means a code smell/a questionable architecture/maintenance nightmare. – Cee McSharpface Jul 07 '19 at 18:24
0

Using "new" keyword in derived class has the same effect as without using "new" regardless the fact there was "virtual" keyword or not.

"virtual" works in pair with "override".

"new" works alone in derived class context only.

If they differ, why in the following example do they behave the same?

See the difference in your outputs:

Base: DoItVirtual1
Derived: DoItVirtual1
Derived: DoItVirtual1

Base: DoItVirtual2
Derived: DoItVirtual2
Base: DoItVirtual2

In overridden virtual method, Derived instance casted back to Base class behaved like Derived instance. This is called polymorphism. In second example, where you used new keyword, runtime could not connect casted instance with Derived class.

Jacek
  • 829
  • 12
  • 31
  • In addition, you can never call the operation (as specified in the base class) from a virtual member of a base class externally. Only derived classes are able to call _base.$$$_ –  Jul 07 '19 at 16:26
0

Virtual members allow derived classes to substitute the implementation, while new members are additional members that hide the members in the base classes with the same name.

class A
{
    public virtual int X() => 1;
}

class B : A
{
    public override int X() => 2;
}

class C : B
{
    public new virtual int X() => 3;
}

class D : C
{
    public sealed override int X() => 4;
}

Test

var d = new D();
var dd = d.X();        // 4
var dc = ((C)d).X();   // 4
var db = ((B)d).X();   // 2
var da = ((A)d).X();   // 2

var c = new C();
var cc = c.X();        // 3
var cb = ((B)c).X();   // 2
var ca = ((A)c).X();   // 2

var b = new B();
var bb = b.X();        // 2
var ba = ((A)b).X();   // 2

var a = new A();
var aa = a.X();        // 1