Overloading across inheritance boundaries in c#?
.net, .net-4.0, c#, clr
Solution
See member lookup process of a name N in a type T (in your case member `Foo` in type `Child`):
First, the set of all accessible (Section 3.5) members named N declared in T and the base types (Section 7.3.1) of T is constructed:
virtual void Foo(int x) // Base
void Foo(object x) // Base
override void Foo(int x) // Child
Declarations that include an override modifier are excluded from the set.
virtual void Foo(int x) // Base
void Foo(object x) // Base
Argument has an integer type. So, best choice here is (argument type matches parameter type)
virtual void Foo(int x) // Base
And this method called. But it is virtual method. And its invoked due to virtual method invocation mechanism:
For every virtual method declared in or inherited by a class, there exists a most derived implementation of the method with respect to that class. The most derived implementation of a virtual method M with respect to a class R is determined as follows:
- If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
- Otherwise, if R contains an override of M, then this is the most derived implementation of M.
- Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to the direct base class of R.
And what is most derived implementation of `virtual void Foo(int x)` method with respect to a class `Child`? Yes, it is
override void Foo(int x) // Child
Which is invoked. Same rules applied in your third sample. But when two options left after overridden method removing, best choice (due to argument type) is non-virtual method.
Problem
After reading this article & that article - I got confused. It says : If there are two methods at different levels of the hierarchy, the "deeper" one will be chosen first, even if it isn't a "better function member" for the call. Also - It turns out that if you override a base class method in a child class, that doesn't count as declaring it. Now let's go back to my question : Case 1 ``` public class Base { public virtual void Foo(int x) { "1".Dump();} } public class Child : Base { public void Foo(object x) { "3".Dump();} public override void Foo(int x) { "2".Dump();} } void Main() { Child c = new Child(); c.Foo(10); //emits 3 } ``` OK.According to the article "deeper" one will be chosen first, even if it isn't a "better function. and it doesn't count the override... So it is right and the program emits "3". ( `Foo(object x)` is executed) Let's change line order of 1 line : Case 2 ``` public class Base { public virtual void Foo(int x) { "1".Dump();} public void Foo(object x) { "3".Dump();} //<line being moved here } public class Child : Base { public override void Foo(int x) { "2".Dump();} } void Main() { Child c = new Child(); c.Foo(10); //emits 2 !!!! } ``` Now it emits "2". Now lets change all int to object and all object to int : Case 3 ``` public class Base { public virtual void Foo(object x) { "1".Dump();} public void Foo(int x) { "3".Dump();} } public class Child : Base { public override void Foo(object x) { "2".Dump();} } void Main() { Child c = new Child(); c.Foo(1); //emits "3" } ``` Questions : Question#1 : in case 2 , `Child` inherited the `Foo(object x)` from its father AND he also overrides a method. but didnt we just say that : It turns out that if you override a base class method in a child class, that doesn't count as declaring it ??? in fact, we didnt also declared the inherited function ... so what is the rule here in this situation ? Question#2 : in case 3 , `Child` inherited the `Foo(int x)` from its father AND he also overrides a method. but now , he chooses its father function.... it seems like `override` is winning only if it has exact match. again , what is the rule here in this situation ?