与可选参数冲突的重载方法
Posted
技术标签:
【中文标题】与可选参数冲突的重载方法【英文标题】:Conflicting overloaded methods with optional parameters 【发布时间】:2011-02-10 02:12:15 【问题描述】:我有两个重载方法,一个带有可选参数。
void foo(string a)
void foo(string a, int b = 0)
现在我打电话:
foo("abc");
有趣的是,第一个重载被调用了。 为什么不将可选值设置为零的第二个重载?
说实话,我本以为编译器会带来错误,至少是警告,以避免无意执行错误的方法。
这种行为的原因是什么?为什么 C# 团队会这样定义它?
【问题讨论】:
这正是导致潜在错误的糟糕语言设计。内部人员也可以很容易地利用它进行企业间谍活动。我希望他们已经阻止语言允许这样做。 【参考方案1】:想象一下,如果情况正好相反。你有一个应用程序。它有一个方法:
void foo(string a)
一切正常。现在,您想再添加一个带有可选参数的重载:
void foo(string a, int b = 0)
轰隆隆!所有方法调用都转到新方法。无论你想要与否。添加方法重载可能会导致整个应用程序发生错误的方法调用。
在我看来,在这种情况下,您将有更多机会破解您(或其他人)的代码。
此外,OptionalAttribute 在 C# 中被忽略,直到 4.0 版,但您可以使用它。有些人确实在 C# 代码中使用它来支持与其他语言(例如 Visual Basic)或 COM 互操作的某些互操作性场景。现在 C# 将它用于可选参数。添加警告/错误可能会为这些应用程序带来重大更改。
可能还有其他一些原因,但这只是我首先想到的。
【讨论】:
它应该显示编译器错误或代码分析警告。 @Locutus 您似乎没有阅读亚历山德拉回答的倒数第二段。【参考方案2】:来自MSDN:
如果两个候选者被判断为同样好,则优先考虑没有可选参数的候选者,在调用中省略了这些参数。这是由于参数较少的候选者普遍偏好重载解决方案的结果。
【讨论】:
【参考方案3】:不需要自动填充任何可选参数的重载优于需要自动填充的重载。但是,在自动填充一个参数和填充多个参数之间没有这样的偏好 - 例如,这将导致编译时错误:
void Foo(int x, int y = 0, int z = 0)
void Foo(int x, int y = 0)
...
Foo(5);
注意 Foo(5, 5) 会被解析为第二种方法,因为这样就不需要自动填写任何可选参数了。
来自 C# 4 规范的第 7.5.3.2 节:
否则如果 MP 的所有参数都有 一个相应的论点,而 默认参数需要是 替换为至少一个可选的 MQ中的参数然后MP优于 MQ。
老实说,我认为在大多数情况下,这是大多数人所期望的行为。当您将基类方法引入混合时会变得很奇怪,但情况总是如此。
【讨论】:
感谢您的回答。还有一个问题:他们为什么要这样定义?是否存在可选参数的重载有意义的场景?它永远不会用默认值调用,对吧?但它可能会导致不必要的错误。我仍然认为编译器应该至少给出一个警告。还有其他一些例子,开发人员必须明确告诉编译器他知道自己在做什么。例如,如果方法中的参数声明为 ref,我也需要在方法调用中显式使用 ref 关键字;否则无法编译。 @Thomas:恐怕我没有任何答案——尽管 Eric Lippert 可能。我不希望您必须向调用代码添加任何 更多 包袱 - 毕竟,默认参数的原因正是为了 减少 您的代码量需要。以上是关于与可选参数冲突的重载方法的主要内容,如果未能解决你的问题,请参考以下文章