Onde aprender sobre o depurador VS ‘nomes mágicos’

Se você já usou o Reflector, provavelmente percebeu que o compilador C # gera tipos, methods, campos e variables ​​locais, que merecem exibição ‘especial’ pelo depurador. Por exemplo, variables ​​locais que começam com ‘CS $’ não são exibidas para o usuário. Existem outras convenções de nomenclatura especiais para tipos de fechamento de methods anônimos, campos de suporte de propriedades automáticas e assim por diante.

Minha pergunta: onde aprender sobre essas convenções de nomenclatura? Alguém sabe sobre alguma documentação?

Meu objective é fazer com que o PostSharp 2.0 use as mesmas convenções.

Estes são detalhes de implementação não documentados do compilador e sujeitos a alterações a qualquer momento. (UPDATE: Veja GeneratedNames.cs nas fonts de C # para os detalhes atuais; a descrição abaixo está um pouco desatualizada.)

No entanto, desde que eu sou um cara legal, aqui estão alguns desses detalhes:

Se você tiver uma variável local não usada que o otimizador remove, emitimos informações de debugging para ela de qualquer maneira no PDB. Colocamos o sufixo __Deleted$ em tais variables ​​para que o depurador saiba que elas estavam no código-fonte, mas não representadas no binário.

Os slots de variável temporária alocados pelo compilador recebem nomes com o padrão CS $ X $ Y, em que X é o “tipo temporário” e Y é o número de temporários alocados até o momento. Os tipos temporários são:

 0 --> short lived temporaries 1 --> return value temporaries 2 --> temporaries generated for lock statements 3 --> temporaries generated for using statements 4 --> durable temporaries 5 --> the result of get enumerator in a foreach 6 --> the array storage in a foreach 7 --> the array index storage in a foreach. 

Tipos temporários entre 8 e 264 são armazenamentos de índice de matriz adicionais para matrizes multidimensionais.

Tipos temporários acima de 264 são usados ​​para temporários envolvendo a declaração fixa que fixa uma string.

Nomes gerados pelo compilador especial são gerados para:

 1 --> the iterator state ("state") 2 --> the value of current in an iterator ("current") 3 --> a saved parameter in an iterator 4 --> a hoisted 'this' in an iterator ("this") 5 --> a hoisted local in an iterator 6 --> the hoisted locals from an outer scope 7 --> a hoisted wrapped value ("wrap") 8 --> the closure class instance ("locals") 9 --> the cached delegate instance ("CachedAnonymousMethodDelegate") a --> the iterator instance ("iterator") b --> an anonymous method c --> anonymous method closure class ("DisplayClass") d --> iterator class e --> fixed buffer struct ("FixedBuffer") f --> anonymous type ("AnonymousType") g --> initializer local ("initLocal") h --> query expression temporary ("TransparentIdentifier") i --> anonymous type field ("Field") j --> anonymous type type parameter ("TPar") k --> auto prop field ("BackingField") l --> iterator thread id m --> iterator finally ("Finally") n --> fabricated method ("FabricatedMethod") o --> dynamic container class ("SiteContainer") p --> dynamic call site ("Site") q --> dynamic delegate ("SiteDelegate") r --> com ref call local ("ComRefCallLocal") s --> lock taken local ("LockTaken") 

O padrão para gerar nomes mágicos é: PC__SI onde:

  • P é CS $ para delegates em cache e instâncias de class de exibição, caso contrário, vazio.
  • N é o nome original associado à coisa, se houver
  • C é o caractere 1 a s listado acima
  • S é um sufixo descritivo (“atual”, “estado” e assim por diante) para que você não precise memorizar a tabela acima ao ler os metadados.
  • Eu sou um número único opcional