【问题标题】:Why could C# overload two methods with the same params as long as one of them has default param?为什么 C# 可以重载具有相同参数的两个方法,只要其中一个具有默认参数?
【发布时间】:2021-11-09 06:53:07
【问题描述】:

我最近注意到 C# 编译器允许方法重载,如下所示:

    public static string foo(string a, bool x = false)
    {
        return "a";
    }
    public static string foo(string a)
    {
        return "b";
    }

据我测试,只要没有给出第二个参数,它总是返回“b”,这是有道理的。但是,我认为编译器确实不应该允许这种类型的重载。请问为什么这个功能是这样设计的,而不是编译器报错?

【问题讨论】:

  • 那么这个问题还是陈述?这实际上是 C# ECMA 规范中称为重载解析的一个非常深入的主题,它可以在编译或运行时发生。说某事应该以不同的方式工作是可以的(也许你已经以各种可以想象的方式完全考虑了这一点,所以他们应该聘请你加入 Roslyn 和运行时团队),但是我们无能为力
  • However, I think the compiler really should not allow this type of overloading. 你为什么这么认为?
  • Why could C# overload two methods with the same params as long as one of them has default param? 显而易见的答案是它们没有具有相同的参数。
  • 你可能会看到这种警告:Method with optional parameter is hidden by overload.
  • 顺便说一句,我发现微软确实在他们的文档中声明了重载解决方案:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…

标签: c# overloading default-value


【解决方案1】:

虽然这样的问题根本无法回答,但由于无法猜测语言设计者的意图,我可能会猜测一下。

通过转换代码以将参数注入调用站点来处理可选参数。所以

public static void Test(int a = 42){...}

...
Test();

将被转换为

public static void Test(int a){...}

...
Test(42);

由编译器。从这一点开始,常规重载解决方案可以运行而不会发生冲突。为什么要这样设计?我不知道,但非直观功能的常见原因是向后兼容性或语言兼容性。

因此,在公共 API 中使用可选参数时要非常小心,这一点很重要。由于库的用户将使用编译它的 API 版本中的默认值。不是它运行的版本。

【讨论】:

    【解决方案2】:

    我无法解释为什么这是设计的一部分,只是简单地解释为什么您会看到在您的测试中偏爱哪种重载。

    如果您查看reference documentation,您会注意到以下三个项目符号来描述重载解决方案:

    • 如果方法、索引器或构造函数的每个参数都是可选的,或者按名称或位置对应于调用语句中的单个参数,并且该参数可以转换为类型参数。
    • 如果找到多个候选者,则会将首选转换的重载决策规则应用于明确指定的参数。忽略可选参数的省略参数。
    • 如果两个候选者被判定为同样优秀,则优先选择没有可选参数的候选者,而该候选者的参数在调用中被省略。重载解析通常更喜欢参数较少的候选。

    我会断言,在您的测试中,第 3 条最适用于您的观察 - 因为您省略了第二个参数并且任何一种方法都同样好,分辨率有利于您的第二种方法,并且您会看到“b”返回。

    【讨论】:

      猜你喜欢
      • 2019-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多