Pourquoi! 0 est-il un type dans Microsoft Intermediate Language (MSIL)?

88

Dans de nombreuses listes MSIL, j'ai observé ce qui suit:

System.Nullable`1<!0> etc ...

ou

class !0 etc ...

Quelle est la signification de !0dans ces circonstances?

Dragno
la source

Réponses:

118

C'est bizarrerie du décompilateur que vous utilisez pour regarder un assembly .NET. C'est le comportement de ildasm.exe, d'autres comme Reflector ou ILSpy réussissent. Le programmeur Microsoft qui l'a écrit a pris un raccourci, il génère une chaîne à partir de l'IL qui affiche simplement l'argument de type tel qu'il est encodé, sans écrire le supplément code pour rechercher le nom de l'argument de type dans les métadonnées.

Vous devez lire !ncomme le n-ième argument de type du type générique. Où! 0 signifie "premier argument de type",! 1 signifie "deuxième argument de type", etc. Pour Nullable <>, vous savez que «! 0» signifie «T» de l'article MSDN.

Vous pouvez également rencontrer quelque chose comme !!T. Deux points d'exclamation indiquent un argument de type pour une méthode générique . Cette fois -ci , ildasm.exe ne regarde le nom de l' argument de type au lieu d'utiliser !!0. Pourquoi le programmeur a pris le raccourci sur les types génériques mais pas sur les méthodes génériques est difficile à rétroconcevoir. Ildasm est un programme assez original et est écrit dans un style de codage C ++ très différent des autres codes C ++ de .NET. Pas aussi discipliné, des chances non nulles que ce soit la mission d'un stagiaire :)

Le suffixe `1 sur" Nullable "est un encodage normal pour les noms de type générique, il indique que le type générique a un argument de type. En d'autres termes, pour Nullable <> vous ne verrez jamais! 1 être utilisé.

Alors lisez simplement !0"T". Ou utilisez un meilleur décompilateur.

Hans Passant
la source
35

C'est un paramètre de type générique.

Ils sont positionnels.

Décompilez du code générique pour voir comment ils sont utilisés (comparez IL vs C #).

leppie
la source
5
Si j'utilise TryRoslyn Je ne comprends pas ... goo.gl/ZZKE38 je reçois !Tet !!T, selon que le paramètre générique est de la classe contenant ou de la méthode ... Le même si j'utilise ildasm
Xanatos
@xanatos Pas toujours. Je vois aussi du code comme ldfld class System.Collections.Generic.Dictionary``2<!0, !1> valuetype System.Collections.Generic.Dictionary``2/Enumerator<!TKey, !TValue>::dictionaryou call instance void class System.Collections.Generic.Dictionary``2<!TKey, !TValue>::Insert(!0, !1, bool). L'IL brut n'utilise de toute façon que l'argument positionnel - il !TKeys'agit déjà d'une tentative de rendre l'IL plus lisible. Peut-être que cela ne fonctionne pas toujours bien? La spécification ECMA utilise toujours la position !0/ !00ainsi.
Luaan