选择不同的重载方法,具体取决于使用空参数调用它的位置
Posted
技术标签:
【中文标题】选择不同的重载方法,具体取决于使用空参数调用它的位置【英文标题】:Different overload method is chosen, depending from where it's called with a null parameter 【发布时间】:2017-07-01 10:35:38 【问题描述】:我有一个具有重载 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 one 重复。我不认为情况完全如此,因为帮助我理解我的问题的重点是,IEnumerable<int>
不是IEnumerable<object>
。
一般来说,这意味着,不能指望任何类型的 IEnumerable 是对象的 IEnumerable,这是我不知道的。
上述帖子未得出此结论。
【问题讨论】:
IEnumerable<int>
不是 IEnumerable<object>
,因此不适用过载。
那为什么我直接用FormatStuff.Format(null);
调用Format函数的时候会出现IEnumerable重载呢?
null
是一个IEnumerable<object>
,它比object
“更具体”,因此选择了重载。如果您使用IEnumerable<int>
调用Format
,则仅适用object
重载。请参阅this answer,其中描述了如何解决重载问题。
Overloading null ambiguity的可能重复
【参考方案1】:
在编译时,每个调用表达式的调用(绑定)重载是静态固定的(除非您在编译时使用dynamic
类型)。仅仅因为您用于参数的表达式在程序运行时碰巧评估为另一种类型,重载不会神奇地改变。
例子:
FormatStuff.Format(null);
编译时类型不存在(null),但由于存在从 null
文字到 object
的隐式转换以及从 null
到 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>
是 IEnumerable<object>
。因此,两种重载都适用,并且首选最具体的重载。
【讨论】:
【参考方案2】:要实现您想要的,您的方法必须能够区分两个方法调用。
当您传递 null
时,Format()
方法不知道您的 null 是 object
还是 IEnumerable<object>
,因为两者都是对象类型。
要解决您的问题,您可以执行以下操作之一:
Format(IEnumerable<int> args)
或
2 通过添加可选参数来更改方法的类型签名。以this为例【讨论】:
以上是关于选择不同的重载方法,具体取决于使用空参数调用它的位置的主要内容,如果未能解决你的问题,请参考以下文章