Em muitas listagens MSIL, observei o seguinte:
System.Nullable`1<!0> etc ...
ou
class !0 etc ...
Qual é o significado de !0nessas circunstâncias?
Respostas:
Essa é uma peculiaridade do descompilador que você usa para examinar um assembly .NET. É o comportamento de ildasm.exe, outros como Reflector ou ILSpy acertam. O programador da Microsoft que o escreveu pegou um atalho, ele gera uma string a partir do IL que apenas exibe o argumento do tipo da forma como está codificado, sem escrever o código extra para pesquisar o nome do argumento do tipo nos metadados.
Você precisa ler !ncomo o enésimo argumento de tipo do tipo genérico. Onde! 0 significa "argumento de primeiro tipo",! 1 significa "argumento de segundo tipo", etc. Para Nullable <>, você sabe que '! 0` significa' T 'do artigo do MSDN.
Você também pode encontrar algo parecido !!T. Dois pontos de exclamação indicam um argumento de tipo para um método genérico . Desta vez, ildasm.exe não procurar o nome argumento de tipo em vez de usar !!0. Por que o programador pegou o atalho em tipos genéricos, mas não em métodos genéricos, é difícil de fazer engenharia reversa. Ildasm é um programa muito peculiar e foi escrito em um estilo de codificação C ++ muito diferente de outros códigos C ++ em .NET. Não tão disciplinado, probabilidade diferente de zero de que esta fosse uma tarefa de estagiário :)
O sufixo `1 em" Nullable "é uma codificação normal para nomes de tipo genérico, ele indica que o tipo genérico tem um argumento de tipo. Em outras palavras, para Nullable <> você nunca verá! 1 sendo usado.
Portanto, simplesmente leia !0como "T". Ou use um descompilador melhor.
Esse é um parâmetro de tipo genérico.
Eles são posicionais.
Decompile algum código genérico para ver como eles são usados (compare IL com C #).
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). O IL bruto usa apenas o argumento posicional de qualquer maneira - o !TKeyjá é uma tentativa de tornar o IL mais legível. Talvez nem sempre funcione bem? A especificação ECMA sempre usa o posicional !0/ !00também.
!Te!!T, dependendo se o parâmetro genérico é da classe que contém ou do método ... O mesmo se eu usar ildasm