【问题标题】:Null literal parameter type overload resolution [duplicate]空字面量参数类型重载解析
【发布时间】:2011-09-13 18:00:31
【问题描述】:

可能重复:
How does the method overload resolution system decide which method to call when a null value is passed?

这是一个关于为什么编译器在传递空文字作为参数时选择某个重载的问题,由 string.Format 重载证明。

当对 args 参数使用空文字时,string.Format 会抛出 ArgumentNullException

string.Format("foo {0}", null);

Format 方法有一些重载。

string.Format(string, object);
string.Format(string, object[]);
string.Format(IFormatProvider, string, object[]);

通过反编译代码运行,从第二种方法抛出空文字 args 的异常。但是,以下示例调用上面的第一个方法(如预期的那样),然后调用第二个方法,该方法调用第三个方法,最终只返回“foo”。

string x = null;
string.Format("foo {0}", x);

string y;
string.Format("foo {0}", y = null);

但是string.Format("foo {0}", null) 调用了上面的第二个方法并导致了一个空异常。在这种情况下,为什么编译器会决定 null 文字匹配第二个方法签名而不是第一个?

【问题讨论】:

  • 如果这包含更一般意义上的可变参数(如果它不是 string.Format 特定的),也许可以扩大标题/范围...
  • Pete,您可能已经意识到这一点(这不是您问题的答案),但尽管我会提到它;为避免此异常,您可以使用String.Format("Testing {0}", String.Empty);。一切顺利。
  • 重复问题:stackoverflow.com/q/5173339/25727。简而言之:重载决议更喜欢更具体的类型。所以它选择了数组,因为object 是 .NET 中最不确定的类型。
  • @Jan:这是否也解释了为什么其他两个示例选择 object 而不是 object[]?
  • 在您的其他两个示例中,不能使用带有 object[] 参数的重载,因为在这种情况下,string 不是 object[] 并且参数的类型是 string

标签: c# .net


【解决方案1】:

我只是猜测object[]object 更具体,并且null 可分配给object[] 前者被选中。 (7.5.3.2 C# 规范中更好的函数成员)。

如果你尝试也会发生同样的情况:

void Foo(object o) {}
void Foo(object[] arr) {}

Foo(null); //Foo(object[]) gets called.

【讨论】:

    【解决方案2】:

    不能给你 100% 的确定性,但我最好的猜测如下......

    如果我亲自编写编译器,并且必须根据传递的参数选择要使用的重载函数,我自然会迭代列表并找到最佳匹配。我想在 C# 编译器中实现了这些方面的一些东西。

    因此,这将向我建议“重载​​ 2”(在您的示例中)在列表中早于“重载 1”,因此找到匹配并且迭代被破坏,或者编译器设置为使用更多后者匹配重载。

    当然,在您的 2 示例中传递 x 和 y。当您将字符串与对象匹配时,很容易匹配到“重载 1”,而字符串无法匹配到 object[],因此“重载 2”不是有效匹配。

    当您直接传递 null 时,它同时匹配“重载 1”和“重载 2”,因此回到列表中第一个找到或最后找到的点。

    编辑:事实证明,编译器必须根据哪些参数更具体来决定。如果对象更具体,则为 object[]。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 2011-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多