选择不同的重载方法,具体取决于使用空参数调用它的位置

Different overload method is chosen, depending from where it's called with a null parameter

我有一个 class 带有重载的 Format 方法。

 class FormatStuff
 {
    public static string Format(object arg)
        => HandleObjectStuff();

    public static string Format(IEnumerable<object> args)
        => HandleListStuff();
 }

现在,当我打电话时

FormatStuff.Format(null);

我以 IEnumerable 参数结束了第二次重载。 但就我而言,我从这样的函数中调用该方法:

 public static string DoStuff(IEnumerable<int> intnumerable)
 {
     StringBuilder sb = new StringBuilder();
     sb.Append(FormatStuff.Format(intnumerable));
     return sb.ToString();
 }

当我像这样调用这个函数时

DoStuff(null);

我在第一个重载中以单个对象参数结束,即使在这两种情况下都将 null 作为参数传递。

为什么会这样,我该怎么做才能结束与 DoStuff 参数类型相匹配的第二次重载?

编辑: 该问题已被标记为可能与 this 个问题重复。我不认为情况完全如此,因为帮助我理解我的问题的重点是 IEnumerable<int> 不是 IEnumerable<object>。 一般来说,这意味着,不能期望任何类型的 IEnumerable 是对象的 IEnumerable,我不知道。 上述post.

中并没有得出这个结论

要实现您想要的效果,您的方法必须能够区分 两个方法调用。 当您传递 null 时,Format() 方法不知道您的 null 是 object 还是 IEnumerable<object>,因为两者都是对象类型。 要解决您的问题,您可以执行以下操作之一:

  • 1 将第二种方法改为Format(IEnumerable<int> args)

  • 2 通过添加可选参数更改方法的类型签名。以this为例

在 compile-time 处每个调用表达式要调用(绑定)的重载是静态固定的(除非您在 compile-time 处使用类型 dynamic)。仅仅因为您用于参数的表达式在程序运行时恰好求值为另一种类型,所以重载不会神奇地改变。

示例:

FormatStuff.Format(null);

compile-time 类型不存在(null),但由于存在从 null 文字到 object 的隐式转换以及从 null 的隐式转换IEnumerable<object>,两个重载都是候选者。在那种情况下,使用 IEnumerable<object> 的重载是首选,因为它更具体。

FormatStuff.Format((object)null);

在这种情况下,表达式的 compile-time 类型是 object,因此只有一个重载适用,并且使用了它。

IEnumerable<int> intnumerable
// ...
FormatStuff.Format(intnumerable);

在上述情况下,您传递的 compile-time 类型是 IEnumerable<int>。这里 int 是一个 value-type。 IEnumerable<int> 不是 compile-time 处的 IEnumerable<object>这个固定在compile-time;不管intnumerable是否恰好在run-time是null,如果non-null,在 run-time.

处的实际类型(一些具体的 class 或实现 IEnumerable<int> 的结构)是什么并不重要
IEnumerable<string> strEnumerable
// ...
FormatStuff.Format(strEnumerable);

最后,在这种情况下,由于 string 是引用类型,因此 IEnumerable<out T> 的 compile-time 协方差适用。所以 IEnumerable<string> IEnumerable<object>。因此,两种重载都适用,最具体的一种是首选。