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 :
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 :
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 :
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 ?
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.
There are 2 things happening:
So basically the lookup rules can choose the method taking an int if it's on a deeper class, but when the method gets called, if it's been overridden it will call the method taking an int on the child class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With