4

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?

Joan Venge
  • 315,713
  • 212
  • 479
  • 689
Dale McCoy
  • 41
  • 1
  • 1
    for 1), I was unable to reproduce the error you see. It seems to compile fine for me when I call it with this: TraceWriter.TraceWrite("", LogLevelENUM.FakeLevel, "", false); – Tim Trout Jun 17 '10 at 13:43
  • OK, that is *weird*. But it happens for me too. Some times (string, LogLevelENUM, string, bool) compiles, and other times it doesn't. I'll have to look harder at that. – Dale McCoy Jun 17 '10 at 15:47
  • Ran your example in VS2022 and did not see the issues you have described. There was no exception and more importantly compiler resolved your call to the second overload. – Grisha Dec 23 '22 at 19:20

3 Answers3

2

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

Tim Trout
  • 1,062
  • 12
  • 20
  • Compiler chooses the second overload in C# 4.0 and higher, because it omits optional parameter and the fourth parameter is of the type Boolean. Thus, it matches to the signature of second overload. Dale McCoy's expectations in his first question are adequate. It seems that his question is not clear, or Dale McCoy had environment issues that he did not share about in his question, but you were able to reproduce. – Grisha Dec 23 '22 at 19:45
0

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);
MrFox
  • 4,852
  • 7
  • 45
  • 81
  • The number of overloads is a result of C# 3.5, and we might go through and clean them up at some point. That aside, this answer raises a follow-up question: If the fifth argument for the third overload isn't really optional, why does the compiler allow it to be specified as such? – Dale McCoy Jun 17 '10 at 15:55
0

For the second question, your call would be resolved to the first overload, because its signature has fewer parameters.

If you'd like it to be resolved to the third overload, then use named arguments in your call, for example like this:

TraceWrite("string", LogLevelENUM.Level, "string", PieceID: "string");
Grisha
  • 305
  • 1
  • 4
  • 12