我刚刚注意到过载解析的奇怪行为。
假设我有以下方法:
public static void DoSomething<T>(IEnumerable<T> items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}
现在,我知道通常会使用少量显式参数来调用此方法,因此为了方便起见,我添加了此重载:
public static void DoSomething<T>(params T[] items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(params T[] items)");
}
现在我尝试调用这些方法:
var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");
但在这两种情况下,过载params
叫做。我本以为IEnumerable<T>
在以下情况下调用的重载List<T>
,因为它似乎是一个更好的匹配(至少对我来说)。
这种行为正常吗?有人能解释一下吗?我在 MSDN 文档中找不到任何相关的明确信息...这里涉及的重载解析规则是什么?
C# 3.0 规范的第 7.4.3 节是此处的相关位。基本上参数数组已扩展,因此您要进行比较:
public static void DoSomething<T>(T item)
and
public static void DoSomething<T>(IEnumerable<T> item)
The T
第一场比赛被推断为List<string>
和T
第二场比赛被推断为string
.
现在考虑参数到参数类型所涉及的转换 - 在第一个转换中是List<string>
to List<string>
;第二个是List<string>
to IEnumerable<string>
。根据 7.4.3.4 中的规则,第一次转换优于第二次转换。
违反直觉的一点是类型推断。如果你把它从等式中去掉,它就会像你期望的那样工作:
var items = new List<string> { "foo", "bar" };
DoSomething<string>(items);
DoSomething<string>("foo", "bar");
此时,每次调用中只有一个适用的函数成员。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)