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
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.
A.methodA(BB)
is invoked, because its argument matches parameter.
A.methodA(AA)
will be chosen, but it is virtual method, so actually call goes to B.method(AA)
- Same as option 2
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
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