Первая часть вашего вопроса (без перегрузки по списку) проста.Давайте рассмотрим вызов Array, поскольку он работает одинаково для обоих вызовов:
Во-первых, вывод типа создает две возможные универсальные реализации вызова: Print<Person[]>(Person[] items)
и Print<Person>(IEnumerable<Person> items)
.
Затем перегрузкаРазрешение вступает в силу, и первое выигрывает, потому что второе требует неявного преобразования, в отличие от первого (см. §7.4.2.3 спецификации C #).Тот же механизм работает для варианта List.
При добавленной перегрузке с помощью вызова List генерируется третья возможная перегрузка: Print<Person>(List<Person> items)
.Аргумент такой же, как и для Print<List<Person>>(List<Person> items)
, но опять же, в разделе 7.4.3.2 предоставляется разрешение на языке
Рекурсивно, составной тип более специфичен, чем другой составной тип (с тем же номеромаргументов типа), если хотя бы один аргумент типа является более конкретным и ни один аргумент типа не является менее конкретным, чем соответствующий аргумент типа в другом.
Таким образом, перегрузка Print<Person>
является более специфичной, чем Print<List<Person>>
перегрузка и версия List побеждает IEnumerable, потому что он не требует неявного преобразования.