c# - 重载、泛型类型推断和 'params' 关键字

标签 c# generics type-inference params-keyword overload-resolution

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

假设我有以下方法:

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)

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");

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

关于c# - 重载、泛型类型推断和 'params' 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1820551/

相关文章:

c# - Action 和 Func<T> 都没有显式转换

typescript - 为什么在使用隐式 Any 时 Typescript 不显示错误?

c# - 是否可以创建与所用键盘相同的键盘布局?

c# - 简化 Linq 表达式

c# - 将 System.Drawing.Icon 转换为 System.Windows.Controls.Image

Java 对具有两个泛型参数的类的泛型类型检查应该只包含相同类型的类

java - 如何从 Class<T> 推断 T 的方法

c++ - C++ 11 auto关键字多少太多了?

c++ - 类型在 SFINAE 中未继承以进行多重继承?

c# - 使用数据集处理分页和 "lazy-loading"?