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.

Original source

Related problems