C# 4 中的重载分辨率和可选参数

Posted

技术标签:

【中文标题】C# 4 中的重载分辨率和可选参数【英文标题】:Overload Resolution and Optional Parameters in C# 4 【发布时间】:2011-03-04 23:10:25 【问题描述】:

我正在处理一些代码,该代码具有七个函数 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 = "");

(所有公共静态、命名空间噪音都被忽略了。)

所以,在这样的背景下: 1)在其他地方,我用四个参数调用TraceWritestring, LogLevelENUM, string, bool,我得到以下错误:

错误 CS1502: 'TraceWrite(string, LogLevelENUM, string, string)' 的最佳重载方法匹配有一些无效参数
错误 CS1503:参数“4”:无法从“布尔”转换为“字符串”

为什么这个调用不能解决第二个重载? (TraceWrite(string, LogLevelENUM, string, bool, string = ""))

2) 如果我用string, LogLevelENUM, string, string 调用TraceWrite,会调用哪个重载?第一个还是第三个?为什么?

【问题讨论】:

for 1),我无法重现您看到的错误。当我用这个调用它时,它似乎编译得很好: TraceWriter.TraceWrite("", LogLevelENUM.FakeLevel, "", false); 好吧,那是奇怪。但它也发生在我身上。有时 (string, LogLevelENUM, string, bool) 会编译,有时则不会。我将不得不更加努力地看待这一点。 【参考方案1】:

编译器将选择重载#1,因为它与参数数量和签名完全匹配。

【讨论】:

【参考方案2】:

你的重载很糟糕,你应该在它们之间做出更多的改变。编译器无法知道您是指第一个还是第三个。

第三个参数的最后一个参数应该没有默认值,第一个参数在最后一个字符串之前应该有一个不同的非字符串参数,或者第三个参数的 PieceID 参数应该是一个 int。

有一个不同的可能更好的解决方案:使用多个默认值。您有很多默认值,它们应该减少重载的数量。使用多个默认值,您可以调用仅指定最后一个值的方法。希望您可以将重载次数减少到 1 或 2。

public static int add(int a = 0, int b = 0)

    return a + b;

add(b: 1);

【讨论】:

重载的数量是 C# 3.5 的结果,我们可能会在某个时候检查并清理它们。除此之外,这个答案引发了一个后续问题:如果第三个重载的第五个参数不是真正可选的,为什么编译器允许这样指定它?

以上是关于C# 4 中的重载分辨率和可选参数的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 4.0 中是不是应该使用重载或可选参数声明方法?

命名参数和可选参数,以及 WCF

C#中可选参数和具名参数的使用

C#4.0中的方法重载与可选参数[重复]

ApiControllerAttribute 和可选参数

重载的方法在 Resharper 中给出“带有可选参数的方法被重载隐藏”警告