C# 使用泛型重载:错误还是特性?

Posted

技术标签:

【中文标题】C# 使用泛型重载:错误还是特性?【英文标题】:C# overloading with generics: bug or feature? 【发布时间】:2011-02-04 21:53:24 【问题描述】:

让我们有一个简化的例子:

void Foo<T>(IEnumerable<T> collection, params T[] items) 

    // ...


void Foo<C, T>(C collection, T item)
    where C : ICollection<T>

    // ...


void Main()

    Foo((IEnumerable<int>)new[]  1 , 2);

编译器说:

类型“System.Collections.Generic.IEnumerable”不能用作泛型类型或方法“UserQuery.Foo(C,T)”中的类型参数“C”。没有从“System.Collections.Generic.IEnumerable”到“System.Collections.Generic.ICollection”的隐式引用转换。

如果我将Main 更改为:

void Main()

    Foo<int>((IEnumerable<int>)new[]  1 , 2);

它会正常工作的。为什么编译器不选择right重载?

【问题讨论】:

IEnumerable 和 ICollection 之间确实没有转换。 @Yossarian:两件事。首先,有一个显式转换。您的意思是说“确实没有隐式引用转换”。其次,问题不是“为什么我会收到‘无隐式转换’错误?”其次,问题是“为什么重载解决算法会选择一个无效的完全匹配候选而不是选择不完全匹配的有效但更差的候选?” 【参考方案1】:

我的猜测是编译器在使用泛型约束之前会选择最佳匹配。在您的示例中,带有约束的方法更可取,因为它没有 params 最后一个参数。

编辑 - Eric Lippert 在他的回答中证实了这一点。

【讨论】:

以上是关于C# 使用泛型重载:错误还是特性?的主要内容,如果未能解决你的问题,请参考以下文章

泛型还是只使用重载?

C# 中的多态、重载和泛型

C#方法重载和泛型接口

C# - 定义泛型函数重载的首选项

C# 非泛型“***”不能与类型实参一起使用的错误

在 C# 中是不是可以通过以下方式重载泛型强制转换运算符?