25

我有两种重载方法,一种带有可选参数。

void foo(string a)  { }  
void foo(string a, int b = 0) { }  

现在我打电话:

 foo("abc");

有趣的是,调用了第一个重载。为什么不将可选值设置为零的第二个重载?

老实说,我本来希望编译器会带来一个错误,至少是一个警告,以避免无意执行错误的方法。

这种行为的原因是什么?为什么 C# 团队会这样定义它?

4

3 回答 3

33

来自MSDN

如果两个候选者被判断为同样好,则优先考虑没有可选参数的候选者,在调用中省略了这些参数。这是对具有较少参数的候选者的重载解决方案的普遍偏好的结果。

于 2010-04-20T11:02:25.773 回答
14

不需要自动填充任何可选参数的重载优于需要自动填充的重载。但是,在自动填写一个参数和填写多个参数之间没有这样的偏好 - 例如,这将导致编译时错误:

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。

老实说,我认为在大多数情况下,这是大多数人所期望的行为。当您将基类方法引入混合时会变得很奇怪,但情况总是如此。

于 2010-04-20T10:56:40.387 回答
7

想象一下,如果它是相反的。你有一个应用程序。它有一个方法:

void foo(string a)  { }   

一切都很好。现在,您想添加一个带有可选参数的重载:

void foo(string a, int b = 0) { }  

繁荣!所有方法调用都转到新方法。无论你想要与否。添加方法重载可能会导致整个应用程序中的错误方法调用。

从我的角度来看,在这种情况下,您将有更多机会破坏您(或其他人)的代码。

此外,直到 4.0 版,C# 中都忽略了OptionalAttribute,但您可以使用它。有些人确实在 C# 代码中使用它来支持与其他语言(例如 Visual Basic)或 COM 互操作的某些互操作性场景。现在 C# 将它用于可选参数。添加警告/错误可能会为这些应用程序引入重大更改。

可能还有其他一些原因,但这只是我首先想到的。

于 2010-04-21T21:18:38.377 回答