重载、泛型类型推断和“参数”;关键词

发布于 2024-08-13 03:58:50 字数 845 浏览 4 评论 0原文

我刚刚注意到过载解析的奇怪行为。

假设我有以下方法:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我的奇迹 2024-08-20 03:58:50

C# 3.0 规范的第 7.4.3 节是此处的相关位。基本上,参数数组已扩展,因此您要进行比较:

public static void DoSomething<T>(T item)

并且

public static void DoSomething<T>(IEnumerable<T> item)

第一个匹配的 T 被推断为 ListT第二个匹配的 code> 被推断为 string

现在考虑参数到参数类型的转换 - 第一个转换是 ListList;第二个是 ListIEnumerable。根据 7.4.3.4 中的规则,第一次转换优于第二次转换。

违反直觉的一点是类型推断。如果您将其从等式中剔除,它将按您期望的方式工作:

var items = new List<string> { "foo", "bar" };
DoSomething<string>(items);
DoSomething<string>("foo", "bar");

此时,每次调用中只有一个适用的函数成员。

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:

public static void DoSomething<T>(T item)

and

public static void DoSomething<T>(IEnumerable<T> item)

The T for the first match is inferred to be List<string> and the T for the second match is inferred to be string.

Now consider the conversions involved for argument to parameter type - in the first one it's List<string> to List<string>; in the second it's List<string> to IEnumerable<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:

var items = new List<string> { "foo", "bar" };
DoSomething<string>(items);
DoSomething<string>("foo", "bar");

At that point, there's only one applicable function member in each call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文