C # перегрузка с помощью дженериков: ошибка или функция? - PullRequest
8 голосов
/ 06 апреля 2010

Давайте рассмотрим следующий упрощенный пример:

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» нельзя использовать в качестве параметра типа «C» в универсальном типе или методе «UserQuery.Foo (C, T)». Не существует неявного преобразования ссылок из System.Collections.Generic.IEnumerable в System.Collections.Generic.ICollection.

Если я изменю Main на:

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

Это будет работать нормально. Почему компилятор не выбирает правильную перегрузку?

Ответы [ 2 ]

15 голосов
/ 06 апреля 2010

Здесь вы найдете ответ на свой вопрос.

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

Пожалуйста, прочитайте также около миллиона комментариев, говорящих мне, что я ошибаюсь для некоторых интересных дополнительных комментариев по этому вопросу.

2 голосов
/ 06 апреля 2010

Я предполагаю, что компилятор выбирает наилучшее соответствие, прежде чем использовать общее ограничение. В вашем примере метод с ограничением предпочтительнее, потому что у него нет params последнего параметра.

Редактировать - Эрик Липперт подтверждает это в своем ответе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...