12

リフレクションを使用してオブジェクトをマッピングしています。これらのオブジェクトはマネージ コードにありますが、リフレクション以外ではソース コードや基になる構造などを確認することはできません。これらすべての包括的な目標は、オブジェクトの基本的なメモリ マップです (SOS.dllDumpObjectおよび!ObjSizeコマンドと同様の機能)。そのため、フィールドとプロパティの両方として「二重にカウント」されているメンバーを特定しようとしています。

例えば:

public class CalendarEntry
{
    // private property 
    private DateTime date { get; set;}

    // public field 
    public string day = "DAY";
}

マッピングされた場合:

  • 田畑
    • k__BackingField
  • プロパティ
    • 日にち

このようなクラスとして:

public class CalendarEntry
{
    // private field 
    private DateTime date;

    // public field 
    public string day = "DAY";

    // Public property exposes date field safely. 
    public DateTime Date
    {
        get
        {
            return date;
        }
        set
        {
                date = value;
        }
    }
}

マッピングされた場合:

  • 田畑
    • 日にち
  • プロパティ
    • 日にち

一見すると、Dateプロパティの「バッキング フィールド」が という名前のフィールドであることはわかりませんdate。このシナリオでは、日付を 2 回カウントしないようにしています。

さらに混乱/複雑なのは、メソッドを介してリストされる対応するフィールドが常にプロパティにあるとは限らないシナリオに遭遇したType.GetFields()ため、すべてのプロパティを完全に無視することはできません。

から返されたコレクション内のフィールドが、Type.GetFields()本質的に から返された対応するプロパティのバッキング フィールドであるかどうかを判断する方法についてのアイデアはありType.GetProperties()ますか?

編集 - から返されたコレクションにリストされている対応するフィールドがプロパティにない条件を判断するのに苦労しましたType.GetFields()。そのような条件に精通している人はいますか?

編集 2 - プロパティのバッキング フィールドが から返されるコレクションに含まれない場合の良い例を見つけましたType.GetFields()。String のフードの下を見ると、次のようになります。

  • オブジェクトには、FirstChar という名前のプロパティが含まれています
  • オブジェクトには Chars という名前のプロパティが含まれています
  • オブジェクトには、Length という名前のプロパティが含まれています
  • オブジェクトには、m_stringLength という名前のフィールドが含まれています
  • オブジェクトには、m_firstChar という名前のフィールドが含まれています
  • オブジェクトには、Empty という名前のフィールドが含まれています
  • オブジェクトには、TrimHead という名前のフィールドが含まれています
  • オブジェクトには TrimTail という名前のフィールドが含まれています
  • オブジェクトには、TrimBoth という名前のフィールドが含まれています
  • オブジェクトには charPtrAlignConst という名前のフィールドが含まれています
  • オブジェクトには、alignConst という名前のフィールドが含まれています

m_firstCharとはプロパティのm_stringLengthバッキング フィールドですが、文字列の実際の内容は Chars プロパティに保持されますFirstCharLengthこれは、文字列内のすべての文字を返すようにインデックス付けできるインデックス付きプロパティですが、文字列の文字を保持する対応するフィールドが見つかりません。その理由について何か考えはありますか?または、インデックス付きプロパティのバッキング フィールドを取得する方法は?

4

3 に答える 3

5

プロパティのバッキング フィールドの名前は、コンパイラの実装の詳細であり、パターンを把握したとしても、将来常に変更される可能性があります。

あなたの質問に対する答えはすでに出ていると思います: ignore all properties

プロパティは、変装した 1 つまたは 2 つの関数にすぎないことを忘れないでください。プロパティは、ソース コードによって明確に要求された場合にのみ、コンパイラによって生成されたバッキング フィールドを持ちます。たとえば、C# では次のようになります。

public string Foo { get; set; }

ただし、クラスの作成者は、このようなコンパイラ生成プロパティを使用する必要はありません。たとえば、プロパティは定数値を取得する場合があり、複数のプロパティはビット フィールドの異なる部分を取得/設定する場合があります。このような場合、プロパティごとに単一のバッキング フィールドが表示されるとは思わないでしょう。これらのプロパティは無視しても問題ありません。コードが実際のデータを見逃すことはありません。

于 2013-01-14T16:50:47.513 に答える
3

すべてのプロパティを完全に無視できます。プロパティにバッキング フィールドがない場合、単にメモリを消費しません。

また、CIL を解析する (しようとする) 意思がない限り、そのようなマッピングを取得することはできません。次のコードを検討してください。

private DateTime today;

public DateTime CurrentDay
{
    get { return today; }
}

todayフィールドとCurrentDayプロパティの間に何らかの関係があることをどのように把握することが期待されますか?

編集:最近の質問について:

のようなコードを含むプロパティがある場合return 2.6;、値はどこにも保持されず、その定数はコードに直接埋め込まれます。

についてstringstringCLRによって特別な方法で処理されます。そのインデクサーを逆コンパイルしようとすると、CLR によって実装されていることがわかります。これらのいくつかの特殊な型 ( string、配列、int、…) については、それらのフィールドを見てサイズを見つけることはできません。他のすべてのタイプについては、できます。

于 2013-01-14T16:50:50.613 に答える
1

他の質問に答えるには:どのような状況で、プロパティにバッキング フィールドがありませんか?

public DateTime CurrentDay
{
    get { return DateTime.Now; }
}

またはプロパティは、他の任意の数のバッキング フィールド/クラスを使用できます

public string FullName 
{
    get {return firstName + " " + lastName;}
}
于 2013-01-14T16:57:36.603 に答える