5

我刚刚注意到重载决议的一个奇怪行为。

假设我有以下方法:

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但在这两种情况下,都会调用with 的重载。我本来希望IEnumerable<T>在 a 的情况下调用重载List<T>,因为它似乎是一个更好的匹配(至少对我来说)。

这种行为正常吗?谁能解释一下?我在 MSDN 文档中找不到任何明确的信息......这里涉及的重载解决规则是什么?

4

1 回答 1

9

C# 3.0 规范的第 7.4.3 节是这里的相关位。基本上参数数组已扩展,因此您正在比较:

public static void DoSomething<T>(T item)

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

第一T场比赛的 被推断为List<string>T第二场比赛的 被推断为string

现在考虑参数到参数类型所涉及的转换 - 在第一个List<string>List<string>; 在第二个它List<string>IEnumerable<string>。根据 7.4.3.4 中的规则,第一次转换优于第二次。

违反直觉的位是类型推断。如果您将其排除在等式之外,它将按您的预期工作:

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

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

于 2009-11-30T15:50:22.653 回答