I don't think you're telling us the whole story. Section 7.3.5.2 of the C# 5 spec (titled "Better function member") says in part:
• Otherwise, if MP is applicable in its normal form and MQ has a params array and is applicable only in its expanded form, then MP is better than MQ.
That seems to be the case here, since the params
version needs to be "expanded" to a zero-length array. And in fact, trying your code locally produces the expected result of calling the non-params
version.
Update: In response to your edit, the answer is now clear: You are calling the methods from Class1
, which means that when performing overload resolution, methods marked as override
are not considered initially. And since a non-overridden method is applicable (albeit in its expanded form,) that is the method chosen.
Specifically, section 7.6.5.1 read in part:
• The set of candidate methods is reduced to contain only methods from the most derived types: For each method C.F in the set, where C is the type in which the method F is declared, all methods declared in a base type of C are removed from the set.
The base class MyMethod()
is excluded from the candidate set, and so it won't be selected by the algorithm.
The precise reasoning behind this behavior is to avoid a manifestation of the "brittle base-class" problem. Suppose we had the following class hierarchy:
class A
{
}
class B : A
{
public void MyMethod(object o) { }
}
And the following call-site:
new B().MyMethod("a string");
That will obviously resolve to the MyMethod()
that takes an object
. But now suppose the creator of A
(perhaps who works on another team) decides A
should have a MyMethod()
, too. So they change their class:
class A
{
public void MyMethod(string s);
}
And now imagine what would happen if we didn't exclude methods from base types. Your call that was originally resolving to B.MyMethod()
all of a sudden would resolve to A.MyMethod()
(since the string
is a better match.) The designers of C# didn't want to allow another person on a totally different team to silently change the meaning of your code.
For more information on brittle base-class issues, Eric Lippert's (old) blog has a number of posts on the topic. Just search around a bit.