Reputation: 31
I've been doing a little reading around the c# spec, and come across a scenario I didn't expect, and was hoping somebody could share some light.
I stumbled across the new
keyword for hiding members of a base class within a derived class, and subsequently a few discussions over when to use new
as opposed to an override
on a virtual
member.
I threw a little code sample in to my IDE, expecting to see a compilation error
public class BaseType
{
public void method()
{
// do nothing
}
}
public class DerivedType : BaseType
{
public new void method()
{
base.method();
}
}
but instead found this to be legal c#. Since the derived class has hidden the presence of method()
, why am I still allowed to call it?
Cheers
Upvotes: 2
Views: 1304
Reputation: 2848
The DerivedType
is hiding the method from the classes which will be inheriting DerivedType
, and not from itself.
Note that, to hide the method, the class has to know there exists a method in it's parent class with the same name and same arguments. Hence a class hiding the method from it's own scope is logically incorrect.
Upvotes: 4
Reputation: 32750
Do not mix method hiding with method overriding. They are two completely different beasts.
When hiding a method, you are only hiding it when accessing the method through the type that hides the method to begin with:
public class Foo
{
public string Blah() { return "Hi from Foo!"; }
}
public class DerivedFoo: Foo
{
public new string Blah() { return "Hi from DerivedFoo!"; }
}
Now we have the following behavior:
void TestFoos()
{
Foo foo = new Foo();
DerivedFoo derivedFoo = new DerivedFoo();
Foo derivedFooInDisguise = derivedFoo as Foo;
Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
Console.WriteLine(derivedFooInDisguise.Blah()); //Outputs "Hi from Foo!"
}
Note, that this behavior is the same even if Blah
is declared as virtual
. The interesting part is the third call. The method is invoked through a Foo
typed object. As its not a virtual call, Foo.Blah()
is called, not DerivedFoo.Blah()
.
Now this is completely different from method overriding where the virtual method call always resolves to the runtime type of the object, not the type through which you are calling it:
public class Foo
{
public virtual string Blah() { return "Hi from Foo!"; }
}
public class DerivedFoo: Foo
{
public override string Blah() { return "Hi from DerivedFoo!"; }
}
Now we have the following behavior:
void TestFoos()
{
Foo foo = new Foo();
DerivedFoo derivedFoo = new DerivedFoo();
Foo derivedFooInDisguise = derivedFoo as Foo;
Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
Console.WriteLine(derivedFooInDisguise.Blah()); ////Outputs "Hi from DerivedFoo!"
}
Upvotes: 3