DebuggerDisplay 属性を使用して表示する内容をデバッガーに指示する (C#、Visual Basic、F#、C++/CLI)
DebuggerDisplayAttribute は、デバッガー変数ウィンドウにオブジェクト、プロパティ、またはフィールドを表示する方法を制御します。 この属性は型 (クラス、構造体、列挙型、デリゲート) に適用できますが、通常はクラスと構造体にのみ適用されます。 基本型に適用した場合、この属性はサブクラスにも適用されます。
DebuggerDisplay
属性には 1 つの引数があります。これは、型のインスタンスの値列に表示される文字列です。 この文字列には中かっこ ({
と }
) を含めることができます。 中括弧の組内のテキストは、フィールド、プロパティ、またはメソッドとして評価されます。
クラスにオーバーライドされた ToString()
メソッドがある場合、デバッガーは既定の {<typeName>}
の代わりにオーバーライドされたメソッドを使用します。 したがって、ToString()
メソッドをオーバーライドした場合、デバッガーは既定の {<typeName>}
ではなくオーバーライドされたメソッドを使用し、DebuggerDisplay
を使用する必要はありません。 両方を使用する場合、DebuggerDisplay
属性はオーバーライドされた ToString()
メソッドよりも優先されます。 DebuggerDisplay
属性は、サブクラスでオーバーライドされた ToString()
メソッドよりも優先されます。
デバッガーがこの暗黙的な ToString()
呼び出しを評価するかどうかは、[ツール]、[オプション]、[デバッグ] ダイアログ ボックスのユーザー設定によって異なります。
重要
[変数ウィンドウにオブジェクトの未加工構造を表示する] チェック ボックス[ツール]、[オプション]、[デバッグ] ダイアログ ボックスでオンになっている場合、DebuggerDisplay
属性は無視されます。
手記
ネイティブ コードの場合、この属性は C++/CLI コードでのみサポートされます。
次の表は、DebuggerDisplay
属性の使用例と出力例を示しています。
特性 | [値] 列に表示される出力 |
---|---|
[DebuggerDisplay("x = {x} y = {y}")] x および y フィールドを持つ型で使用されます。 |
x = 5 y = 18 |
[DebuggerDisplay("String value is {getString()}")] パラメーターの構文は、言語によって異なる場合があります。 そのため、注意して使用してください。 |
String value is [5, 6, 6] |
DebuggerDisplay
は、名前付きパラメーターを受け入れることもできます。
パラメーター | 目的 |
---|---|
Name 、Type |
これらのパラメーターは、変数ウィンドウの Name 列と Type 列に影響します。 (コンストラクターと同じ構文を使用して文字列に設定できます)。これらのパラメーターを過剰に使用したり、誤って使用したりすると、混乱を招く出力が発生する可能性があります。 |
Target 、TargetTypeName |
属性がアセンブリ レベルで使用される場合のターゲットの種類を指定します。 |
autoexp.cs ファイルは、アセンブリ レベルで DebuggerDisplay 属性を使用します。 autoexp.cs ファイルは、Visual Studio が .NET オブジェクトに使用する既定の展開を決定します。 DebuggerDisplay 属性の使用方法の例については、autoexp.cs ファイルを調べるか、autoexp.cs ファイルを変更してコンパイルして既定の展開を変更することができます。 autoexp.cs ファイルを変更する前に、必ずバックアップしてください。
autoexp.csをビルドするには、VS2015 の開発者コマンド プロンプトを開き、次のコマンドを実行します。
cd <directory containing autoexp.cs>
csc /t:library autoexp.cs
autoexp.dll への変更は、次のデバッグ セッションで取得されます。
DebuggerDisplay での式の使用
DebuggerDisplay 属性では、中かっこ内で一般的な式を使用できますが、この方法はお勧めしません。
DebuggerDisplay の一般的な式は、ターゲット型の現在のインスタンスに対してのみ、this
ポインターに暗黙的にアクセスできます。 この式には、エイリアス、ローカル、またはポインターに対するアクセスはありません。 式がプロパティを参照している場合、それらのプロパティの属性は処理されません。 たとえば、フィールド count
が 8 の場合、C# コード [DebuggerDisplay("Object {count - 2}")]
は Object 6
表示されます。
DebuggerDisplay で式を使用すると、次の問題が発生する可能性があります。
式の評価はデバッガーで最も負荷の高い操作であり、式は表示されるたびに評価されます。 これにより、コードのステップ実行でパフォーマンスの問題が発生する可能性があります。 たとえば、コレクションまたはリスト内の値を表示するために使用される複雑な式は、要素の数が多い場合に非常に遅くなる可能性があります。
式は、式が書き込まれた言語のエバリュエーターではなく、現在のスタック フレームの言語の式エバリュエーターによって評価されます。 これにより、言語が異なる場合に予期しない結果が発生する可能性があります。
式を評価すると、アプリケーションの状態が変わる可能性があります。 たとえば、プロパティの値を設定する式は、実行中のコードのプロパティ値を変更します。
式の評価で発生する可能性のある問題を減らす 1 つの方法は、操作を実行して文字列を返すプライベート プロパティを作成することです。 その後、DebuggerDisplay 属性は、そのプライベート プロパティの値を表示できます。 次の例では、このパターンを実装します。
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public sealed class MyClass
{
public int count { get; set; }
public bool flag { get; set; }
private string DebuggerDisplay
{
get
{
return string.Format("Object {0}", count - 2);
}
}
}
",nq" サフィックスは、最終的な値を表示するときに引用符を削除するように式エバリュエーターに指示します (nq = 引用符なし)。
例
次のコード例は、DebuggerBrowsable
と DebuggerTypeProxy
と共に DebuggerDisplay
を使用する方法を示しています。 デバッガー変数ウィンドウ (ウォッチ ウィンドウなど) で表示すると、次のような展開が生成されます。
名前 | 値 | 型 |
---|---|---|
鍵 | "three" | オブジェクト {string} |
価値 | 3 | object {int} |
[DebuggerDisplay("{value}", Name = "{key}")]
internal class KeyValuePairs
{
private IDictionary dictionary;
private object key;
private object value;
public KeyValuePairs(IDictionary dictionary, object key, object value)
{
this.value = value;
this.key = key;
this.dictionary = dictionary;
}
public object Key
{
get { return key; }
set
{
object tempValue = dictionary[key];
dictionary.Remove(key);
key = value;
dictionary.Add(key, tempValue);
}
}
public object Value
{
get { return this.value; }
set
{
this.value = value;
dictionary[key] = this.value;
}
}
}
[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable
{
public Hashtable hashtable;
public MyHashtable()
{
hashtable = new Hashtable();
}
private string DebuggerDisplay { get { return "Count = " + hashtable.Count; } }
private class HashtableDebugView
{
private MyHashtable myhashtable;
public HashtableDebugView(MyHashtable myhashtable)
{
this.myhashtable = myhashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[myhashtable.hashtable.Count];
int i = 0;
foreach (object key in myhashtable.hashtable.Keys)
{
keys[i] = new KeyValuePairs(myhashtable.hashtable, key, myhashtable.hashtable[key]);
i++;
}
return keys;
}
}
}
}