C# 参数:(必需,可选)vs(必需,必需,可选)

C# 参数:(必需,可选)vs(必需,必需,可选),c#,overloading,optional-parameters,C#,Overloading,Optional Parameters,我定义了以下方法: void Write(string fileContent, string fileName, string container = StorageBlobContainers.ProfilePictures) 代码编译没有问题,因此我编写了代码来执行它(从不同的文件): 但出于某种原因,它似乎什么也没做。经过几分钟的努力,我终于找到了问题所在。在同一类的某个地方,已经有一个Write函数定义如下: void Write(string filePath, string co

我定义了以下方法:

void Write(string fileContent, string fileName, string container = StorageBlobContainers.ProfilePictures)
代码编译没有问题,因此我编写了代码来执行它(从不同的文件):

但出于某种原因,它似乎什么也没做。
经过几分钟的努力,我终于找到了问题所在。在同一类的某个地方,已经有一个
Write
函数定义如下:

void Write(string filePath, string container = StorageBlobContainers.ProfilePictures)
{
  if (!File.Exists(filePath))
    return string.Empty;
  ...

这真的让我很困惑,因为它确实编译得很好,当然,这是有道理的,因为一个方法有3个参数签名,另一个有2个参数签名,但这不是很模糊和/或容易出错吗?对我来说,似乎没有一种方法是可以选择的“合乎逻辑的”。为什么选择第二个而不是另一个呢?

是的,方法解析可能会很棘手,所以在编写多个重载时一定要记住这一点。他们不应该像现在这样对你模棱两可。编译器只是选择了最短的匹配项,这正是它应该选择的,因为有文档证明它可以做到这一点

您可以做两件事:

  • 重命名其中一个方法。这将使方法解析对您和编译器来说是小菜一碟,而且绝对清晰
  • 将两个参数都设置为所需的最后一个参数。这将使方法的分辨率再次非常清晰:两个参数与三个参数
规定(在过载解决方案中,第7.5.3节):

7.5.3.2更好的功能部件

为了确定更好的函数成员,将构造一个精简的参数列表a,该列表仅包含参数表达式本身,其顺序与它们在原始参数列表中出现的顺序相同。 每个候选函数成员的参数列表按以下方式构造:

•如果功能成员仅适用于扩展形式,则使用扩展形式

没有相应参数的可选参数将从参数列表中删除

•对参数进行重新排序,使其与参数列表中的相应参数位于同一位置

(……)

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

(等等)

因此,在您的例子中,重载解析会考虑带有参数的可选参数,因此第二个参数(带有可选参数)比您预期的参数(有三个参数)更具体地匹配您的调用(带有两个参数),因此在C规范中被认为是“更好的”

(取决于可能更改的版本)第1.6.6.5节涉及方法重载。此外,此问题与您所问的问题相同,即指向以下MSDN文章的链接

其中包含相关章节

如果两个候选者被判定为同等优秀,则优先选择没有可选参数的候选者,因为调用中省略了这些参数。这是因为对于参数较少的候选者,重载解析的一般偏好


“为什么选择第二种语言而不是另一种?”——因为这是语言的规则。如果你愿意,我们可以从语言规范中抹去灰尘,并指出导致这一点的具体原因,但这不太可能让你走得更远。为什么第二种方法不是一个合乎逻辑的选择?您正在调用一个具有2个字符串参数的方法,所选的方法是具有2个字符串参数的方法。另外,请记住,可选参数是在版本1之后添加到语言中的,仅仅返回到旧代码并添加默认值的行为不应该导致以前编译的代码无法编译或选择其他方法。
void Write(string filePath, string container = StorageBlobContainers.ProfilePictures)
{
  if (!File.Exists(filePath))
    return string.Empty;
  ...