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

时间:2017-02-13 12:30:19

标签: c# overloading

我有一个带有重载格式方法的类。

 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.FormatFunctionParameter(intnumerable));
     return sb.ToString();
 }

当我将此功能称为

DoStuff(null);

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

为什么这和我该怎么做才能在与DoStuff参数类型相匹配的第二个重载中结束?

修改 该问题已标记为this一个可能的副本。我认为情况并非完全如此,因为帮助我理解我的问题的重点是,IEnumerable<int>不是IEnumerable<object>。 一般来说,这意味着,不能指望任何类型的IEnumerable都是IEnumerable对象,我不知道。 这个结论没有在上述帖子中得出。

2 个答案:

答案 0 :(得分:2)

在编译时为每个调用表达式静态修复哪个调用(绑定)重载(除非在编译时使用类型dynamic)。只是因为用于参数的表达式恰好在程序运行时计算为另一种类型,所以重载不会神奇地改变。

示例:

FormatStuff.Format(null);

编译时类型不存在(null),但由于存在从null字面到object的隐式转换以及从null到{{1的隐式转换同样,两个重载都是候选者。在这种情况下,首选IEnumerable<object>的重载是首选,因为它更具体。

IEnumerable<object>

在这种情况下,表达式的编译时类型为FormatStuff.Format((object)null); ,因此只应用一个重载,并使用它。

object

在上面的例子中,你传递的编译时类型是IEnumerable<int> intnumerable // ... FormatStuff.Format(intnumerable); 。这里IEnumerable<int>是值类型。编译时int不是IEnumerable<int>这是在编译时修复的; 在运行时IEnumerable<object>恰好是intnumerable并不重要,如果非空,则无关紧要实际类型(实现null的一些具体类或结构)是在运行时。

IEnumerable<int>

最后,在这种情况下,由于IEnumerable<string> strEnumerable // ... FormatStuff.Format(strEnumerable); 是引用类型,string的编译时协方差适用。因此,IEnumerable<out T> IEnumerable<string>。因此,两种过载均适用,并且最具体的一种是优选的。

答案 1 :(得分:0)

要实现您的目标,您的方法必须能够区分两个方法调用。 当您通过null时,Format()方法无法知道您的null是object还是IEnumerable<object>,因为它们都是object类型。 要解决您的问题,您可以执行以下操作之一:

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

OR

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