2 votes

Appel d'une méthode générique

Supposons que j'ai une méthode générique. Quelle est la différence entre appeler la méthode en spécifiant le type et l'appeler sans.

Quand devient-il obligatoire de préciser le type ?

Write(1);
Write<int>(1);
Write<string>("test"); 
Write("test");

private static void Write<T>(T param)
{
    Console.WriteLine(param);
}

5voto

poke Points 64398

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.

3voto

Trevi Awater Points 921

Ce n'est pas obligatoire dans cette situation car le paramètre param est le générique (le compilateur le résout ainsi).

Cela signifie qu'il est obligatoire chaque fois que l'argument de type n'est pas fourni en tant que paramètre.

2voto

nvoigt Points 20484

Il devient obligatoire de spécifier le type lorsque le compilateur ne peut pas l'inférer, ou lorsque vous n'êtes pas satisfait de ce que le compilateur infère.

1voto

Gabor Marton Points 537

Il n'y a pas de différence entre

Write<string>("test");
Write("test");

Mais, il y a une différence, lorsque vous spécifiez non pas exactement le type de paramètre, mais le convertible, par exemple

Write<object>("test");
Write("test");

Essayez d'imprimer le type de paramètre et vous verrez la différence.

private static void Write<T>(T param)
{
    Console.WriteLine(typeof(T));
    Console.WriteLine(param);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X