Say I have the following simple two methods:
class Question
{
public void MyMethod()
{
Console.WriteLine("no params here");
}
public void MyMethod(object o = null)
{
Console.WriteLine("an object here");
}
}
and I invoke one like so:
new Question().MyMethod();
It results in the no params method's call, writing "no params here".
I understand that I can still call the other, e.g. like
new Question().MyMethod(null);
but my question is, why doesn't the compiler warn me of a possible ambiguity or force me to be particular? And how does it decide what to call? Simply the one with less parameters?
And how does it decide what to call?
It applies the rules in the MS specification or ECMA standard (take your pick). Overloading is really complicated - particularly by the time you've got type inference, inheritance, optional parameters, typeless arguments (e.g. null
, default
, method groups or lambda expressions) involved.
In this case, it's relatively simple. Both methods are applicable, and neither is "better" than the other in terms of argument conversions, because there aren't any arguments. There are then tie-break rules - and the one that's important in this case is (ECMA version):
If neither function member was found to be better, and all parameters of MP have a corresponding argument whereas default arguments need to be substituted for at least one optional parameter in MQ, then MP is better than MQ. Otherwise, no function member is better.
In other words, it's not ambiguous because one method has no optional parameter without a corresponding argument, and one did.
Note that it's not a matter of "fewer" optional parameters that needed substituting automatically - it's "were there any or not".
As an example of this, consider:
class Question
{
public void MyMethod(int x = 1) {}
public void MyMethod(int x = 1, int y = 2) {}
}
class Test
{
static void Main()
{
// Ambiguous
new Question().MyMethod();
// Unambiguous
new Question().MyMethod(0);
}
}
The first call (no arguments) is ambiguous because both applicable methods have optional parameters with no corresponding arguments.
The second call (one argument) picks the method with a single parameter, because even though there is an optional parameter, it has a corresponding argument - whereas the method with two parameters still has an optional parameter with no corresponding arguments.