Overload on inheritance borders in C #?

After reading this article and that article - I got confused.

It says:

If there are two methods at different levels of the hierarchy, the first will be selected “deeper”, even if it is not the “best member function” to call.

Also -

It turns out that if you override the method of the base class in a child class that is not considered to be a declaration of it.

Now 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

the “deeper” will be selected first, even if it is not a “better function” and does not account for overriding ...

So, this is correct, and the program returns "3". (running Foo(object x) )

Change line of order 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 a "2".

Now change all int to an object and the whole 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 Foo(object x) from his father. And he also redefines the method.

but , we simply did not say that:

It turns out that if you override the method of the base class in a child class that is not considered to be its declaration

???

in fact, we also did not declare the inherited function ... so what is the rule here in this situation?


Question No. 2: in case 3, Child inherited Foo(int x) from his father. And he also redefines the method.

but now he selects the function of his father ....

it seems that override wins only if it has an exact match.

again, what is the rule here in this situation?


+7
source share
3 answers

See the process of finding an element of name N in type T (in your case, a member of Foo in type Child ):

First, a set of all available (section 3.5) elements is created with the name N declared in T and the basic types (section 7.3.1) T:

 virtual void Foo(int x) // Base void Foo(object x) // Base override void Foo(int x) // Child 

Ads containing an override modifier are excluded from the set.

 virtual void Foo(int x) // Base void Foo(object x) // Base 

The argument is an integer type. So, the best choice is here (argument type matches parameter type)

 virtual void Foo(int x) // Base 

And this method is called. But this is a virtual method. And its call is caused by the virtual method invocation mechanism:

For every virtual method declared or inherited by a class, there is a most derived implementation of the method with respect to this class. The most derivative implementation of the virtual method M with respect to the class R is defined as follows:

  • If R contains the introduced virtual declaration 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 R.

And what is the derived implementation of the virtual void Foo(int x) method with respect to the Child class? Yes this

 override void Foo(int x) // Child 

Called. The same rules apply in your third sample. But when two options remain after an overridden method deletion, the best choice (due to the type of argument) is not a virtual method.

+3
source

2 things happen:

  • When choosing a method to call, the compiler will obey the rules according to related articles - i.e. a deeper method will be chosen to a finer one, even if a finer one is a more specific correspondence.
  • If you call an overridden method, it will always call an overridden method (this is a separate choice for choosing the method that is called), the method "only" for calling the base method is subclassed and uses base.MyMethod (..)

Thus, basically search rules can select a method that takes an int if it is in a deeper class, but when the method is called if it has been overridden, it will call a method that takes an int in the child class.

+3
source

I think you just messed up your facts by reading two articles. It should behave like any other normal overridden function since there is no overload in the child class and therefore there is nothing to choose from. Let's take a simple example:

 public class A { public virtual void Foo() { Console.WriteLine("A.Foo() called"); } } public class B: A { public override void Foo() { Console.WriteLine("B.Foo() called"); } } void Main() { new B().Foo(); } 

What is the expected result? Obviously, without thinking twice, someone will say that they called B.Foo (). Well, in your case the same thing happens. It doesn't matter that the base class has the best overloaded method, the child class simply wins it. Do not overload things.

About case 3, I'm not quite sure about this, but it happens here that the compiler tries to implicitly convert to an object, and then discovers that there is a deeper method with the same signature and therefore the rule

if there are two methods at different levels of the hierarchy, the first one will be selected “deeper”, even if it is not the “best member function” to call

and now, when he moves to the base class, he notices that there is a better method that can be used and therefore calls this method.

PS: the above explanation is based on results that have been discovered and may not necessarily be the exact causes of the above behavior.

+1
source

All Articles