使用可选参数冲突重载方法

Tho*_*mas 24 parameters overloading optional-parameters c#-4.0

我有两个重载方法,一个带有可选参数.

void foo(string a)  { }  
void foo(string a, int b = 0) { }  
Run Code Online (Sandbox Code Playgroud)

现在我打电话给:

 foo("abc");
Run Code Online (Sandbox Code Playgroud)

有趣的是第一次重载被调用.为什么第二次重载的可选值设置为零?

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

这种行为的原因是什么?为什么C#团队以这种方式定义它?

Dea*_*ing 32

来自MSDN:

如果判断两个候选者同样好,则优先选择没有可选参数的候选者,该参数在调用中被省略.这是对具有较少参数的候选者的重载分辨率的一般偏好的结果.


Jon*_*eet 14

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

void Foo(int x, int y = 0, int z = 0) {}
void Foo(int x, int y = 0) {}
...
Foo(5);
Run Code Online (Sandbox Code Playgroud)

请注意,Foo(5,5)将被解析为第二种方法,因为它不需要自动填充任何可选参数.

从C#4规范的7.5.3.2节:

否则,如果MP的所有参数都具有相应的参数,而默认参数需要替换MQ中的至少一个可选参数,则MP优于MQ.

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

  • 感谢您的回答.还有一个问题是:为什么他们这样定义?是否存在使用可选参数的重载有意义的场景?永远不会使用默认值调用它,对吗?但它可能导致不必要的错误.我仍然认为compliler应该至少给出一个警告.还有其他一些例子,开发人员必须明确告诉编译器他知道他在做什么.例如,如果方法中的参数声明为ref,我也需要在方法调用中显式使用ref关键字; 否则它将无法编译. (2认同)
  • @Thomas:我担心我的理由没有任何答案 - 尽管Eric Lippert可能.我不希望你必须在调用代码中添加任何*更多*行李 - 毕竟,默认参数的原因恰恰是*减少*你需要的代码量. (2认同)

Ale*_*ina 7

试想一下,如果相反的话.你有一个申请.它有一个方法:

void foo(string a)  { }   
Run Code Online (Sandbox Code Playgroud)

一切都很好.现在,您想要使用可选参数添加一个重载:

void foo(string a, int b = 0) { }  
Run Code Online (Sandbox Code Playgroud)

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

从我的角度来看,在这种情况下,你有更多的机会来打破你(或别人的)代码.

此外,在版本4.0中,在C#中忽略了OptionalAttribute,但您可以使用它.有些人确实在C#代码中使用它来支持某些与其他语言(如Visual Basic)或COM互操作的互操作性方案.现在C#将它用于可选参数.添加警告/错误可能会为这些应用程序带来重大变化.

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

  • 它应该显示编译器错误或代码分析警告. (4认同)