Давайте иметь следующий упрощенный пример:
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);
}
В компиляторе говорится:
Тип 'Система. Наборы. Универсальный. IEnumerable' не может использоваться в качестве параметра типа 'C' в универсальном типе или методе 'UserQuery. Нечто (C, T)'. Нет никакого неявного ссылочного преобразования из 'Системы. Наборы. Универсальный. IEnumerable' к 'Системе. Наборы. Универсальный. ICollection'.
Если я изменяюсь Main
кому:
void Main()
{
Foo<int>((IEnumerable<int>)new[] { 1 }, 2);
}
Это будет работать хорошо. Почему компилятор не выбирает правильную перегрузку?
Здесь дан ответ на ваш вопрос.
http://blogs.msdn.com/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
Пожалуйста, также прочтите примерно миллион комментариев, в которых говорится Мне кажется, что я ошибаюсь в некоторых интересных дополнительных комментариях по этому вопросу.
Я предполагаю, что компилятор выбирает наилучшее соответствие, прежде чем использовать общее ограничение. В вашем примере предпочтительнее использовать метод с ограничением, поскольку он не имеет последнего параметра params
.
Править - Эрик Липперт подтверждает это в своем ответе.