Conflicting overloaded methods with optional parameters
I have two overloaded methods, one with an optional parameter.
void foo(string a) { }
void foo(string a, int b = 0) { }
now I call:
foo("abc");
interestingly the first overload is called. why not the second overload with optional value set to zero?
To be honest, I would have expect the compiler to bring an error, at least a warning to avoid unintentional execution of the wrong method.
What's the reason for this behaviour? Why did the C# team define it that way?
Solution 1:
From MSDN:
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
Solution 2:
An overload which doesn't require any optional parameters to be filled in automatically is preferred to one which does. However, there's no such preference between filling in one argument automatically and filling in more than one - so for example, this will cause a compile-time error:
void Foo(int x, int y = 0, int z = 0) {}
void Foo(int x, int y = 0) {}
...
Foo(5);
Note that Foo(5, 5) would be resolved to the second method, because then it doesn't require any optional parameters to be automatically filled in.
From section 7.5.3.2 of the C# 4 spec:
Otherwise if 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.
I think in most cases this is the behaviour most people would expect, to be honest. It gets weird when you introduce base class methods into the mix, but that's always been the case.
Solution 3:
Just imagine if it were the opposite. You had an application. It had a method:
void foo(string a) { }
Everyting worked fine. Now, you want to add one more overload with an optional parameter:
void foo(string a, int b = 0) { }
Boom! All method calls go to the new method. Whenever you want it or not. Adding a method overload might cause wrong method calls all over the application.
From my perspective, in this case you'd have much more opporunities to break your (or someone else's) code.
Also, OptionalAttribute was ignored in C# until version 4.0, but you could use it. And some people did use it in C# code to support certain interoperability scenarios with other languages, such as Visual Basic, or for COM interop. Now C# uses it for optional parameters. Adding warnings/errors may introduce a breaking change for those applications.
There might be some other reasons, but this is just what comes to my mind first.