Question

Je viens de remarquer un comportement étrange avec une résolution de surcharge.

Supposons que j'ai la méthode suivante:

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

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

Maintenant, je sais que cette méthode sera souvent appelée avec un petit nombre d'arguments explicites. C'est pourquoi, par commodité, j'ajoute cette surcharge:

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

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

J'essaie maintenant d'appeler ces méthodes:

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

Mais dans les deux cas, la surcharge avec params est appelée. Je me serais attendu à ce que la IEnumerable<T> surcharge soit appelée dans le cas d'un List<T>, car cela semble mieux correspondre (du moins pour moi).

Ce comportement est-il normal? Quelqu'un pourrait-il l'expliquer? Je ne trouvais aucune information claire à ce sujet dans les documents MSDN ... Quelles sont les règles de résolution de surcharge impliquées ici?

Était-ce utile?

La solution

La section 7.4.3 de la spécification C # 3.0 est le bit pertinent ici. Fondamentalement, le tableau de paramètres est développé, vous comparez donc:

public static void DoSomething<T>(T item)

et

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

Le T pour la première correspondance est List<string> et le string pour la deuxième correspondance IEnumerable<string>.

Considérons maintenant les conversions impliquées pour l'argument du type de paramètre. Dans le premier cas, il s'agit de <=> à <=>; dans la seconde c'est <=> à <=>. La première conversion est meilleure que la seconde selon les règles de 7.4.3.4.

Le bit contre-intuitif est l'inférence de type. Si vous retirez cela de l'équation, cela fonctionnera comme prévu:

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

À ce stade, il n'y a qu'un seul membre de fonction applicable dans chaque appel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top