views:

175

answers:

2

Let's have a following simplified example:

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

Compiler says:

The type 'System.Collections.Generic.IEnumerable' cannot be used as type parameter 'C' in the generic type or method 'UserQuery.Foo(C, T)'. There is no implicit reference conversion from 'System.Collections.Generic.IEnumerable' to 'System.Collections.Generic.ICollection'.

If I change Main to:

void Main()
{
    Foo<int>((IEnumerable<int>)new[] { 1 }, 2);
}

It will work ok. Why compiler does not choose the right overload?

+15  A: 

Your question is answered here.

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

Please also read the approximately one million comments telling me that I am wrong for some interesting additional commentary on this issue.

Eric Lippert
Ok. Thank you for quick answer:) I have to always wait a long time before I can accept the answer:)
TN
I knew that I read this article and I was looking for it ... but obviously you know your blog better than me and find the articles faster - which is kind of fair ... ^^
tanascius
+2  A: 

My guess is that the compiler chooses the best match before it uses the generic constraint. In your example the method with the constraint is preferable because it doesn't have a params last parameter.

Edit - Eric Lippert confirms this in his answer.

Ben Lings
Yes. Thank you too:)
TN