简体   繁体   中英

C# overload with override

I can surely answer to this question by myself writing a dummy test but I want to know what people think about the question. Here it is:

Which method will be call when we have both at the same time overloading and overriding? I am only considering Type overloading and not arity overloading and when Type the overload are related.

Let me throw you an example:

class AA {}
class BB : AA {}

class A {
    public virtual void methodA(AA anAA) { Console.Write("A:methodA(AA) called"); }
    public virtual void methodA(BB aBB) { Console.Write("A:methodA(BB) called"); }
}

class B : A {
    public override void methodA(AA anAA) { Console.Write("B:methodA(AA) called"); }
}

new B().methodA(new BB());     // Case 1
new B().methodA(new AA());     // Case 2
new B().methodA((AA)new BB()); // Case 3

Can you tell what will happen in case 1, 2, and 3?

I personally think that overloadaing is evil and that there is no consistent thinking that could lead to a predictable answer. And that is completely base on a convention implemented in the compiler+vm.

EDIT: If you have some doubt about why overload is evil you can read the blog post from Gilad Brach

Thanks

No, it is entirely predictable. The method signature is resolved first - that is, the overload is determined first. Then, the most overridden method is called. So the output will be:

  • A:methodA(BB) called
  • B:methodA(AA) called
  • B:methodA(AA) called

The method taking an instance of AA will be called in the second two cases, because this is the type of the reference that is passed in, and it is B's version that is called. Note that even this would produce the same result:

A instance = new B();
instance.methodA((AA)new BB()); // Case 3

Overridden methods are excluded from method set when compiler determines which method to call. See member lookup algorithm. So, when you call methodA on type B , set of members with name methodA from type B and it's base type will be constructed:

override B.methodA(AA)
virtual A.methodA(AA)
virtual A.methodA(BB)

Then members with ovveride modifier removed from set:

virtual A.methodA(AA)
virtual A.methodA(BB)

This group of methods is the result of lookup. After that overload resolution applied to define which member to invoke.

  1. A.methodA(BB) is invoked, because its argument matches parameter.
  2. A.methodA(AA) will be chosen, but it is virtual method, so actually call goes to B.method(AA)
  3. Same as option 2

I think the result will be this

case 1 : Console.Write("A:methodA(BB) called");

case 2 : Console.Write("B:methodA(AA) called");

case 3 : Console.Write("B:methodA(AA) called");

in case 3 it will look the type that it's passed, and it's B

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM