Pourquoi une méthode générique qui contrainte T à la classe aurait des instructions de boxe dans le code MSIL génère?
J'étais assez surprise par cela depuis que t est certainement contraint à un type de référence, le code généré ne doit pas nécessairement effectuer Toute boxe. p>
voici le code C #: p> voici le IL généré: p> Pourquoi cela est généré? p> Comment éviter cela? P> P>
4 Réponses :
Je crois que cela est destiné à la conception. Vous n'êtes pas contraignant à une classe spécifique, il est donc probablement le casse-couché. Par conséquent, pourquoi vous voyez que l'IL inclut la boxe. P>
Je voudrais essayer ce code avec où T :Class p>
Si vous faites T :Class, pourquoi vous embêter avec les génériques?
Parce que vous pouvez contraindre à des niveaux plus élevés ... comme IsomeInterface ...
Chris, si t était un objet, n'aurait-il pas déjà été encadré avant de pousser sur la pile? Pourquoi une opération de boxe doit-elle être effectuée dessus? Je m'attendrais à ce que l'opérateur == vérifie l'égalité de référence si t était un objet, cela ne nécessiterait donc pas d'opérations d'ONU / boxe.
@RoberTharevey Juste pour poser ce différend âgé de 10 ans au repos et pour confirmer que ce malheureux C # comportement prévaut toujours en 2019, les instructions de boxe injustifiées sont effectivement émises même lorsqu'ils sont contraignants à une classe dérivée où T: Class code>, par opposition à ce que l'OP spécifié
où T: classe code>, dans laquelle le second implique probablement un "type de référence le moins dérivé" (et note - pas i >
system.Object code>, à partir duquel
system.valuetype code> dérive théoriquement).
Je ne suis pas sûr de savoir pourquoi une boxe est devence. Un moyen possible d'éviter la boxe est de ne pas l'utiliser. Juste recompiler sans la boxe. Ex: ... Si vous économisez sur un fichier recomp_srp.msil, vous pouvez simplement recompiler comme tel: P> ildasme / dll recomp_srp.msil P> < p> Et il fonctionne bien sans la boxe à ma fin: p> ... Bien sûr, je l'ai changé de protégé au public, vous auriez besoin de faire le changement de retour encore et fournir le reste de votre implémentation. P> p>
MDR. Bien que ce soit en effet une solution appropriée (et, si je me vante, un qui arrive maintenant être de voie trivialement disponible pour moi i>, grâce aux efforts effrontés d'un voyage pénible et de longue date à l'insuissance et mystique Mixed C # / IL B> Assemblée), je doute que la plupart des personnes soient prêtes à passer de C # à IL pour faciliter cette solution de bogue.
Vous n'avez pas à vous soucier des performances de la performance des instructions CODE> BOX CODE> car si son argument est un type de référence, l'instruction BOX CODE> ne fait rien. Bien qu'il soit toujours étrange que l'instruction code> code> ait été créée (peut-être la baisse / la conception plus facile à la génération de code?). P>
Suivi des points sur quelques points. Tout d'abord, ce bug survient pour les deux méthodes dans une classe générique forte> avec contrainte remarque quelques problèmes supplémentaires avec le premier exemple. Au lieu de simplement La bonne nouvelle cependant , allongé-à ici , n'est qu'aucune de ces questions. Malgré les différences de code IL générées pour les deux exemples ci-dessus, la X64 JIT FORT> génère du code presque identique pour eux. Le résultat suivant est destiné à .NET Framework 4.7.2 Mode de sortie fort> avec optimisation "non supprimé". P> où T: classe code> ainsi que méthodes génériques forte> avec cette même contrainte ( dans une classe générique ou non générique). Il ne se produit pas pour une méthode non générique (sinon identique) qui utilise
objet code> au lieu de
t code>:
ldnull code>, nous avons un
iniobj it> appellez injustement ciblant inutilement une variable locale en excès
TMP code>. P>
Le gist de la réponse que j'ai lié est qu'une instruction de boxe sur un type de référence est efficacement un NOP. Cela permet au compilateur d'émettre librement des instructions de boxe pouvant être supprimées par le JIT pour des types construits fermés créés avec un type de référence en tant qu'argument de type générique. Dans votre cas (puisque
t code> est contraint comme un type de référence) Aucune des deux instructions de boxe émises ne serait jamais exécutée.
Ceux-ci seront de toute façon non ops pour les types de référence, donc ce n'est pas un gros problème, mais j'ai une suspicion. Vous compilez avec
/ optimiser + code>?
Merci Andrew. J'ai effectué des recherches sur les génériques et la boxe, mais je n'ai pas trouvé cette question. Je suppose que, que le compilateur ne se dérange pas de mettre en œuvre une logique spéciale pour cela - car l'opération de la boîte finit par ne rien faire. Pas sûr, si c'est la bonne façon de le faire, mais si vous voulez poster cela comme une réponse, je vais le marquer comme accepté. Acclamations!
En réponse à votre question Pavel - ne le pensez pas, c'est-à-dire d'une version de débogage, et les paramètres du projet ont la case «Optimiser le code» décoché.