Génériques et méthode surchargée de classe de différence – problème de priorité

Tout d’abord, désolé pour le titre, mais je ne pouvais penser à rien de mieux…

Mon problème peut être présenté par exemple de code simple:

public static class Test { public static int GetInt(T source) { return Convert.ToInt32(source); } } public static class Convert { public static int ToInt32(byte source) { return 30; } public static int ToInt32(object source) { return 10; } } 

Pourquoi Console.WriteLine(Test.GetInt(20)); imprime 10 au lieu de 30 ?

J’ai toujours pensé que les génériques de .NET sont résolus par JIT pendant l’exécution. Pourquoi alors la gigue n’est pas assez intelligente pour savoir qu’il existe une ToInt32(byte) , qui convient à notre type de paramètre d’ byte ici?

Ce comportement fait que l’appel de méthodes de classe statiques Convert aboutit à des opérations de boxing / unboxing pour des types simples.

Le compilateur doit décider au moment de la compilation quelle méthode choisir. Il n’émet aucun code pour décider au moment de l’exécution laquelle des deux surcharges doit être sélectionnée. Étant donné que vous n’avez fourni aucune preuve au compilateur C # que GetInt(T source) ne fonctionne qu’avec byte structures d’ byte , le compilateur doit choisir l’autre surcharge.

Ou laissez-moi vous mettre dans une perspective différente: si vous supprimez la ToInt32(object) , votre programme ne parvient pas à comstackr.

Le compilateur décide lors de la compilation de la méthode à exécuter.

Je vois à travers Reflector pour le code IL et a trouvé ceci –

 .method public hidebysig static int32 GetInt(!T source) cil managed { .maxstack 1 .locals init ( [0] int32 CS$1$0000) L_0000: nop L_0001: ldarg.0 L_0002: box !T L_0007: call int32 ConsoleApplication1.Convert::ToInt32(object) <-- HERE L_000c: stloc.0 L_000d: br.s L_000f L_000f: ldloc.0 L_0010: ret } 

Comme mentionné par Jon Skeet ici , vous pouvez appeler la méthode byte en utilisant dynamic qui fournit des informations typées au moment de l’exécution au lieu du moment de la compilation.

 public static class Test { public static int GetInt(T source) { dynamic dynamicSource = source; return Convert.ToInt32(dynamicSource ); } }