Перегрузка, вывод универсального типа и ключевое слово 'params'

StackOverflow https://stackoverflow.com/questions/1820551

Вопрос

Я только что заметил странное поведение с разрешением перегрузки.

Предположим, что у меня есть следующий метод :

public static void DoSomething<T>(IEnumerable<T> items)
{
    // Whatever

    // For debugging
    Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}

Теперь я знаю, что этот метод часто будет вызываться с небольшим количеством явных аргументов, поэтому для удобства я добавляю эту перегрузку :

public static void DoSomething<T>(params T[] items)
{
    // Whatever

    // For debugging
    Console.WriteLine("DoSomething<T>(params T[] items)");
}

Теперь я пытаюсь вызвать эти методы :

var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");

Но в обоих случаях перегрузка с params называется.Я бы ожидал, что IEnumerable<T> перегрузка, вызываемая в случае List<T>, потому что это кажется лучшим совпадением (по крайней мере, мне).

Является ли такое поведение нормальным ?Кто - нибудь может это объяснить ?Я не смог найти никакой четкой информации об этом в документах MSDN...Какие правила разрешения перегрузки здесь задействованы ?

Это было полезно?

Решение

Здесь уместен раздел 7.4.3 спецификации C # 3.0.По сути, массив параметров расширен, поэтому вы сравниваете:

public static void DoSomething<T>(T item)

и

public static void DoSomething<T>(IEnumerable<T> item)

Тот Самый T предполагается, что первое совпадение будет List<string> и тот T предполагается, что второе совпадение будет string.

Теперь рассмотрим преобразования, необходимые для преобразования аргумента в тип параметра - в первом случае это List<string> Для List<string>;во втором случае это List<string> Для IEnumerable<string>.Первое преобразование является лучшим, чем второе, в соответствии с правилами, изложенными в разделе 7.4.3.4.

Парадоксальный бит - это вывод типа.Если вы исключите это из уравнения, оно будет работать так, как вы ожидаете:

var items = new List<string> { "foo", "bar" };
DoSomething<string>(items);
DoSomething<string>("foo", "bar");

На этом этапе в каждом вызове есть только один применимый член функции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top