VSデバッガーの「マジックネーム」について学ぶ場所


110

リフレクターを使用したことがあれば、C#コンパイラーが型、メソッド、フィールド、ローカル変数を生成することに気づいたでしょう。これらはデバッガーによる「特別な」表示に値します。たとえば、「CS $」で始まるローカル変数はユーザーに表示されません。匿名メソッドのクロージャタイプ、自動プロパティのバッキングフィールドなどには、他にも特別な命名規則があります。

私の質問:これらの命名規則についてどこで学ぶべきですか?誰かがいくつかのドキュメントについて知っていますか?

私の目的は、PostSharp 2.0で同じ規則を使用することです。

回答:


209

これらは文書化されていないコンパイラの実装の詳細であり、いつでも変更される可能性があります。(更新:GeneratedNames.cs 現在の詳細についてはC#のソースを参照してください。以下の説明はやや古くなっています。)

ただし、私はいい人なので、以下にその詳細の一部を示します。

オプティマイザーが削除する未使用のローカル変数がある場合は、とにかくそのデバッグ情報をPDBに出力します。この__Deleted$ような変数にサフィックスを付けて、デバッガーがそれらがソースコード内にあるがバイナリでは表されないことを認識できるようにしました。

コンパイラーによって割り当てられる一時変数スロットには、CS $ X $ Yというパターンの名前が付けられます。Xは「一時的な種類」、Yはこれまでに割り当てられた一時的な数です。一時的な種類は次のとおりです。

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.  

8〜264の一時的な種類は、多次元配列用の追加の配列インデックスストレージです。

264を超える一時的な種類は、文字列を修正するfixedステートメントを含む一時的なものに使用されます。

コンパイラが生成した特別な名前が生成されます。

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")

魔法の名前を生成するパターンは次のP<N>C__SIとおりです。

  • Pは、キャッシュされたデリゲートおよび表示クラスインスタンスのCS $です。それ以外の場合は空です。
  • Nは、もしあれば、Thingに関連付けられた元の名前です
  • Cは、上記の1からsまでの文字です。
  • Sは説明的なサフィックス(「現在」、「状態」など)であるため、メタデータを読み取るときに上記の表を覚えておく必要はありません。
  • 私はオプションの一意の番号です

2
ありがとうございました!C#コンパイラが生成するクラスと同じようにPostSharpクロージャクラスを適切に動作させることができるかどうかを確認します。
Gael Fraiteur

7
@SLaks:一時的な一時的なものの反対。耐久性のある一時変数は、基本的に名前のないローカル変数です。スタックには、スタックフレームの存続期間中存続する特定の場所があります。短期間の一時ファイルは、ストレージが必要になったときにスタックにプッシュされ、不要になったときにポップオフされます。永続的なテンポラリーはデバッグがはるかに簡単ですが、テンポラリーのライフタイムをはるかに長くすることができます。最適化がオフの場合、永続的な一時ファイルを生成します。
Eric Lippert、2010年

私はクロージャクラスに似た概念を持っていますが、フィールドとしてホイストされたパラメータを持つ代わりに、ローカル変数として持っています。これはパラメーターに対してはうまく機能しますが、「this」が「ldarg.0」ではなく、インデックス4のローカル変数であることをデバッガーに伝える方法は?魔法の名前はありますか?
Gael Fraiteur

23
@Eric-この応答をC#5.0(async / await)で生成された名前で更新できますか?私はいくつかの新しいプレフィックスを見てきました:)
Gael Fraiteur
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.