What is the use case for this inheritance idiosyncrasy?
c#, inheritance, mono
Solution
The `new` modifier causes member hiding, which breaks the polymorphic relationship in your class hierarchy. The `SayHi` method of `B` is treated as distinct (not an override) from `A`’s (thus the choice of the word “new” as keyword). `C`’s method then overrides `B`’s, not `A`’s (which remains hidden).
Therefore, when you call `SayHi` on a `C` instance through an `A` reference, the runtime would resolve it against the `A` type, not the `C` type (within which `SayHi` is a “new” method inherited from `B`).
If, on the other hand, you were to run:
B p = new C();
p.SayHi();
…you would get the expected polymorphic result:
From C
Edit: Since you requested a use-case, here’s one. Before the introduction of generics in .NET Framework 2.0, member hiding was sometimes used as a means of altering the return types of inherited methods in derived classes (something you can't do when overriding) in order to return more specific types. For example:
class ObjectContainer
{
private object item;
public object Item
{
get { return item; }
set { item = value; }
}
}
class StringContainer : ObjectContainer
{
public new virtual string Item
{
get { return base.Item as string; }
set { base.Item = value as string; }
}
}
class QuotedStringContainer : StringContainer
{
public override string Item
{
get { return "\"" + base.Item + "\""; }
}
}
The `Item` property of the `ObjectContainer` class returns a plain `object`. However, in `StringContainer`, this inherited property is hidden to return a `string` instead. Thus:
ObjectContainer oc = new StringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since StringContainer.Item is now resolved
The `QuotedStringContainer` class overrides the `Item` property of `StringContainer`, inheriting its `string` return type; however, it is still hidden from the `object`-returning `Item` property of `ObjectContainer`. If it were not this way, there would be no way of reconciling their disparate return types…
ObjectContainer oc = new QuotedStringContainer();
object o = oc.Item; // Valid, since ObjectContainer.Item is resolved
string s1 = oc.Item; // Not valid, since ObjectContainer.Item is still resolved
string s2 = ((StringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
// (polymorphism!)
string s3 = ((QuotedStringContainer)oc).Item;
// Valid, since QuotedStringContainer.Item is now resolved
Problem
When inheriting an inherited class, the new / override behaviour is not what I would expect: ``` $ cat Program.cs using System; class A { public virtual void SayHi() { Console.WriteLine("From A"); } } class B : A { public new virtual void SayHi() { Console.WriteLine("From B"); } } class C : B { public override void SayHi() { Console.WriteLine("From C"); } } public class Program { public static void Main() { A p = new C(); p.SayHi(); } } $ ./Program.exe From A ``` As class C overrides the sayHi() method I would expect the output to be `From C`. Why does the B class's `new` modifier take precedence here? What is the use case for that? Especially as it breaks the obvious use case of having C really override A. Note that the above code was run on Mono 2.10 running on a Debian-derived distro. But I have confirmed the same behaviour using the C# compiler in MS Visual Studio.