Sovraccarico, inferenza di tipo generico e parola chiave "params"
-
10-07-2019 - |
Domanda
Ho appena notato uno strano comportamento con risoluzione del sovraccarico.
Supponi di avere il seguente metodo:
public static void DoSomething<T>(IEnumerable<T> items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(IEnumerable<T> items)");
}
Ora, so che questo metodo verrà spesso chiamato con un piccolo numero di argomenti espliciti, quindi per comodità aggiungo questo sovraccarico:
public static void DoSomething<T>(params T[] items)
{
// Whatever
// For debugging
Console.WriteLine("DoSomething<T>(params T[] items)");
}
Ora provo a chiamare questi metodi:
var items = new List<string> { "foo", "bar" };
DoSomething(items);
DoSomething("foo", "bar");
Ma in entrambi i casi viene chiamato il sovraccarico con params
. Mi sarei aspettato che il sovraccarico IEnumerable<T>
fosse chiamato nel caso di un List<T>
, perché sembra una corrispondenza migliore (almeno per me).
Questo comportamento è normale? Qualcuno potrebbe spiegarlo? Non sono riuscito a trovare chiare informazioni al riguardo nei documenti MSDN ... Quali sono le regole di risoluzione del sovraccarico coinvolte qui?
Soluzione
La sezione 7.4.3 della specifica C # 3.0 è il bit rilevante qui. Fondamentalmente l'array di parametri è espanso, quindi stai confrontando:
public static void DoSomething<T>(T item)
e
public static void DoSomething<T>(IEnumerable<T> item)
Il T
per la prima partita viene dedotto come List<string>
e il string
per la seconda partita viene dedotto come IEnumerable<string>
.
Ora considera le conversioni coinvolte per argomento a tipo di parametro - nella prima è <=> a <=>; nel secondo è <=> a <=>. La prima conversione è migliore della seconda per le regole in 7.4.3.4.
Il bit controintuitivo è l'inferenza del tipo. Se lo elimini dall'equazione, funzionerà come previsto:
var items = new List<string> { "foo", "bar" };
DoSomething<string>(items);
DoSomething<string>("foo", "bar");
A quel punto, c'è solo un membro della funzione applicabile in ogni chiamata.