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.

new from B is hiding the virtual overload in C. Change p to type B and you'll see the output from C
–
asawyerJun 14 '12 at 18:48

The question is "what is the use case for this?" but the actual question asked is "why does it do this?". I'm curious what the use case for this is -- intentionally defeating inheritance in a way that's non-obvious to the consumers of your API seems incredibly dangerous.
–
ChuuJun 14 '12 at 20:15

5 Answers
5

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:

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…

Thank you. I understand how changing B would run the C's method, but is there a use case for breaking the polymorphic relationship between A and C? The guy programming C might have good reason to override A's method, but I fail to see the use case for preventing that, no matter if B is defined as new or override.
–
dotancohenJun 15 '12 at 17:07

1

Since C derives from B which derives from A, there is no direct polymorphic relationship between C and A, but only an indirect one via B. If the B–A chain is broken, then C has no further claim to A, since B broke channel
–
DouglasJun 15 '12 at 17:33

I see, that does make sense. Thank you Douglas.
–
dotancohenJun 15 '12 at 18:19

Thank you for the link and the mention of page. I still don't see a use case for this behaviour, though, whereas the use case of overriding A from C regardless of B is quite obvious.
–
dotancohenJun 15 '12 at 17:10

Because the C class is not overriding the SayHi method in the A class, it's overriding the 'new' method in B. Since your cast is to A, the compiler resolves that as being a call to A.SayHi() rather than C.SayHi()

@dotancohen Yes, because making the method in B private exposes the underlying A method to C to be overridden, giving the expected result. Since you have a public B method, it is the one being overridden.
–
NominSimJun 15 '12 at 17:30