Le compilateur tentera de résoudre l'argument du type au moment de la compilation. Dans les cas où cela est possible, cela est fait automatiquement sans que vous ayez à spécifier un type explicite. Dans tous les autres cas, lorsque le compilateur n'est pas en mesure de déterminer l'argument de type, il lance une erreur et vous ne pouvez pas compiler votre application.
Dans votre exemple Write(1)
l'argument 1
est de type int
. Le compilateur déduit donc que T
doit être int
donc l'appel est équivalent à Write<int>(1)
. De même avec Write("test")
, "test"
est de type string
donc le compilateur déduira que T
est string
.
Cela fonctionne généralement sur le type au moment de la compilation de l'argument que vous passez à la fonction. Ainsi, si vous avez une chaîne de caractères dont le type à la compilation est object
, T
serait object
:
object arg = "foo";
Write(arg); // arg is object
// this is equivalent to this:
Write<object>(arg);
Ainsi, bien que vous passiez une chaîne, son type à la compilation est object
donc c'est la seule information que le compilateur est capable d'utiliser ici.
En outre, vous pouvez spécifier explicitement l'argument type chaque fois que vous voulez que le compilateur utilise un type différent de l'argument de compilation de ce que vous lui passez. Dans l'exemple ci-dessus, vous pourriez utiliser Write<object>(1)
ce qui causerait l'entier 1
pour être jeté dans object
. Cependant, dans la pratique, cela va généralement à l'encontre de l'objectif des méthodes génériques et peut avoir des conséquences réelles même si vous n'avez pas besoin d'accéder au type du paramètre réel au moment de la compilation. Par exemple, les types de valeurs seraient mis en boîte lorsqu'ils sont passés en tant que object
mais les méthodes génériques vous permettent de les conserver en tant que types de valeur - rappelez-vous qu'une définition de méthode générique (il en va de même pour les types) est en quelque sorte équivalente à la spécification d'une surcharge avec tout autre valide valeur d'argument de type générique (vous avez donc généralement une copie infinie de méthodes).
Bien sûr, l'inférence de type du compilateur fonctionne également avec des arguments multiples :
void Write<T1, T2>(T1 arg1, T2 arg2)
{ … }
Write(1, "foo");
// is equivalent to
Write<int, string>(1, "foo");
Cependant, lorsque le compilateur n'est pas capable de déduire ne serait-ce qu'un seul argument de type, vous devrez spécifier todo d'entre eux dans l'appel.