Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about "override" vs. "new" in C#

I'm having the following classes:

class Base
{
    public virtual void Print()
    {
        Console.WriteLine("Base");
    }
}

class Der1 : Base
{
    public new virtual void Print()
    {
        Console.WriteLine("Der1");
    }
}

class Der2 : Der1
{
    public override void Print()
    {
        Console.WriteLine("Der2");
    }
}

This is my main method:

Base b = new Der2();
Der1 d1 = new Der2();
Der2 d2 = new Der2();

b.Print();
d1.Print();
d2.Print();

The output is Base, Der2, Der2.

As far as I know, Override won't let previous method to run, even if the pointer is pointing to them. So the first line should output Der2 as well. However Base came out.

How is it possible? How the override didn't work there?

like image 428
iTayb Avatar asked Jun 01 '10 20:06

iTayb


People also ask

What is the difference between new and override?

The new modifier is used to define ShowDetails in the ConvertibleCar class. The override modifier is used to define ShowDetails in the Minivan class.

What is the difference between the new and override keywords when overriding a class method?

The override keyword is used to extend or modify a virtual/abstract method, property, indexer, or event of base class into a derived class. The new keyword is used to hide a method, property, indexer, or event of base class into derived class.

Can we override a method without virtual keyword?

You cannot override a non-virtual or static method. The overridden base method must be virtual , abstract , or override . An override declaration cannot change the accessibility of the virtual method. Both the override method and the virtual method must have the same access level modifier.

Can I override with different parameters?

No, this would be overloading.


3 Answers

You've never actually overriden the Base version of Print(). You've only hidden it with a separate virtual method (named the same) in Der1.

When you use the new keyword on a method signature - you are telling the compiler that this is a method that happens to have the same name as a method of one of your base classes - but has no other relation. You can make this new method virtual (as you've done) but that's not the same as overriding the base class method.

In Der2 when you override Print you are actually overriding the 'new' version that you declared in Der1 - not the version is Base. Eric Lippert has an excellent answer to a slightly different question that may help you reason about how virtual methods are treated in the C# language.

In your example, when you call Print, you are calling it in the first case through a reference of type Base - so the hidden (but not overriden) version of Print is called. The other two calls are dispatched to Der1's implementation, because in this case, you've actually overriden the method.

You can read more about this in the MSDN documentation of new and override.

What you may have intended to do with Der1 (as you did with Der2) is to use the override keyword:

class Base 
{ 
    public virtual void Print() 
    { 
        Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base
    public override void Print() 
    { 
        Console.WriteLine("Der1"); 
    } 
} 
like image 163
LBushkin Avatar answered Oct 17 '22 08:10

LBushkin


It's because Der1 does not override Print, it replaces it with a brand new method that happens to have the same name (this is caused by the use of the new keyword). So, when the object is cast to Base it calls Print in Base; there is no override to call..

like image 6
Fredrik Mörk Avatar answered Oct 17 '22 09:10

Fredrik Mörk


override will replace the previous method, but as your Der1 class doesn't override Print() (it Shadows it, to use a VB-ism), then the most overriden verion of Base's Print() is called, which happens to be the version it defines

like image 1
Rowland Shaw Avatar answered Oct 17 '22 09:10

Rowland Shaw