重载、泛型类型推断和“参数”;关键词
我刚刚注意到过载解析的奇怪行为。
假设我有以下方法:
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
。我本来希望在 List
的情况下调用 IEnumerable
重载,因为它似乎是更好的匹配(至少对我来说)。
这种行为正常吗?有人能解释一下吗?我在 MSDN 文档中找不到任何相关的明确信息...这里涉及的重载解析规则是什么?
I just noticed a strange behavior with overload resolution.
Assume that I have the following method :
public static void DoSomething<T>(IEnumerable<T> items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}
Now, I know that this method will often be called with a small number of explicit arguments, so for convenience I add this overload :
public static void DoSomething<T>(params T[] items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(params T[] items)");
}
Now I try to call these methods :
var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");
But in both cases, the overload with params
is called. I would have expected the IEnumerable<T>
overload to be called in the case of a List<T>
, because it seems a better match (at least to me).
Is this behavior normal ? Could anyone explain it ? I couldn't find any clear information about that in MSDN docs... What are the overload resolution rules involved here ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C# 3.0 规范的第 7.4.3 节是此处的相关位。基本上,参数数组已扩展,因此您要进行比较:
并且
第一个匹配的
T
被推断为List
和T
第二个匹配的 code> 被推断为string
。现在考虑参数到参数类型的转换 - 第一个转换是
List
到List
;第二个是List
到IEnumerable
。根据 7.4.3.4 中的规则,第一次转换优于第二次转换。违反直觉的一点是类型推断。如果您将其从等式中剔除,它将按您期望的方式工作:
此时,每次调用中只有一个适用的函数成员。
Section 7.4.3 of the C# 3.0 specification is the relevant bit here. Basically the parameter array is expanded, so you're comparing:
and
The
T
for the first match is inferred to beList<string>
and theT
for the second match is inferred to bestring
.Now consider the conversions involved for argument to parameter type - in the first one it's
List<string>
toList<string>
; in the second it'sList<string>
toIEnumerable<string>
. The first conversion is a better than the second by the rules in 7.4.3.4.The counterintuitive bit is the type inference. If you take that out of the equation, it will work as you expect it to:
At that point, there's only one applicable function member in each call.