使用泛型C#重载:错误还是功能?

时间:2010-04-06 16:52:59

标签: c# generics c#-3.0 constraints overloading

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

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

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

2 个答案:

答案 0 :(得分:15)

你的问题在这里得到解答。

http://blogs.msdn.com/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

还请阅读大约一百万条评论,告诉我在这个问题上有一些有趣的补充评论我错了。

答案 1 :(得分:2)

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

编辑 - Eric Lippert在答案中证实了这一点。