Overload Resolution and Optional Parameters in C#

2019-06-24 15:23发布

问题:

I am working with some code that has seven overloads of a function TraceWrite:

void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, bool LogToFileOnly, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, string PieceID, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, LogWindowCommandENUM LogWindowCommand, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, bool UserMessage, int UserMessagePercent, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, string PieceID, LogWindowCommandENUM LogWindowCommand, string Data = "");
void TraceWrite(string Application, LogLevelENUM LogLevel, string Message, LogWindowCommandENUM LogWindowCommand, bool UserMessage, int UserMessagePercent, string Data = "");

(All public static, namespacing noise elided above and throughout.)

So, with that background:
1) Elsewhere, I call TraceWrite with four arguments: string, LogLevelENUM, string, bool, and I get the following errors:

error CS1502: The best overloaded method match for 'TraceWrite(string, LogLevelENUM, string, string)' has some invalid arguments
error CS1503: Argument '4': cannot convert from 'bool' to 'string'

Why doesn't this call resolve to the second overload? (TraceWrite(string, LogLevelENUM, string, bool, string = ""))

2) If I were to call TraceWrite with string, LogLevelENUM, string, string, which overload would be called? The first or the third? And why?

回答1:

The compiler will choose overload #1 because it has an exact match for the number of parameters and the signature.



回答2:

Your overloads are bad, you should make more difference between them. The compiler cannot know whether you meant the first or the third.

Either the third should have no default value for its last argument, the first should have a different non-string argument before the last string or the PieceID argument of the third should be an int.

There is a different possible better solution: use multiple defaults. You have so many defaults they should reduce the number of overloads. With multiple default values you can call a method with only specifiying the last value. Hopefully you can reduce the number of overloads to 1 or 2.

public static int add(int a = 0, int b = 0)
{
    return a + b;
}
add(b: 1);