デバッガ表示属性によるデバッグ機能の拡張
更新 : 2007 年 11 月
デバッガ表示属性を使用すると、開発した型の実行時の動作を指定し、その動作を最もよく理解している開発者が、その型がデバッガに表示されるときの表示形式を指定することもできます。さらに、Target プロパティを提供するデバッガ表示属性は、ソース コードに関する知識を持たないユーザーがアセンブリ レベルで適用できます。DebuggerDisplayAttribute 属性では、デバッガの変数ウィンドウでの型やメンバの表示形式を制御できます。DebuggerBrowsableAttribute 属性では、デバッガの変数ウィンドウでフィールドやプロパティを表示するかどうか、またその表示形式を決定できます。DebuggerTypeProxyAttribute 属性では、型の代替型つまりプロキシを指定し、デバッガ ウィンドウでの型の表示形式を変更できます。プロキシ (代替型) を指定した変数を表示すると、元の型の代わりにプロキシがデバッガ表示ウィンドウに表示されます。デバッガの変数ウィンドウには、プロキシ型のパブリック メンバのみが表示されます。プライベート メンバは表示されません。
DebuggerDisplayAttribute の使用
DebuggerDisplayAttribute コンストラクタの引数は 1 つです。この引数は、型のインスタンスの値列に表示される文字列です。この文字列には、中かっこ ({ と }) を含めることができます。中かっこで囲まれたテキストは、式として評価されます。たとえば、次の C# コードでは、正符号 (+) を選択して MyHashtable のインスタンスのデバッガ表示を拡張すると "Count = 4" が表示されます。
[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
public int count = 4;
}
式で参照されるプロパティに適用されている属性は処理されません。C# コンパイラでは、対象型の現在のインスタンスについて、このような参照に暗黙的にのみアクセスできる一般的な式を使用できます。この式には制限があり、エイリアス、ローカル、またはポインタへはアクセスできません。C# コードでは、対象型の現在のインスタンスのみについて、this ポインタに暗黙的にアクセスできる一般的な式を中かっこに囲んで使用できます。
たとえば、C# オブジェクトにオーバーライドされた ToString() がある場合、デバッガはそのオーバーライドを呼び出し、標準的な {<typeName>} ではなくオーバーライドの結果を表示します。そのため、オーバーライドされた ToString() がある場合、DebuggerDisplayAttribute を使用する必要はありません。両方を使用すると、DebuggerDisplayAttribute 属性が ToString() オーバーライドよりも優先されます。
DebuggerBrowsableAttribute の使用
デバッガ ウィンドウに表示されるフィールドやプロパティの表示形式を指定するには、DebuggerBrowsableAttribute をフィールドまたはプロパティに適用します。この属性のコンストラクタは、DebuggerBrowsableState 列挙値のいずれかを受け取ります。この列挙値は、次のいずれかの状態を指定します。
Never は、メンバがデータ ウィンドウに表示されないことを示します。たとえば、この値をフィールドの DebuggerBrowsableAttribute で使用すると、フィールドが階層構造から削除されます。型インスタンスの正符号 (+) をクリックしてそれを囲む型を展開しても、このフィールドは表示されません。
Collapsed は、メンバは表示されるが既定では展開されないことを示します。これが既定の動作です。
RootHidden は、メンバ自体は表示されず、そのメンバが配列やコレクションの場合、その内在オブジェクトが表示されることを示します。
メモ : |
---|
DebuggerBrowsableAttribute は、.NET Framework Version 2.0 の Visual Basic ではサポートされません。 |
DebuggerBrowsableAttribute を使用して、後続のプロパティがクラスのデバッグ ウィンドウに表示されないようにするコード例を次に示します。
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
DebuggerTypeProxy の使用
型のデバッグ ビューを大幅に変更しても、型自体を変更しないときは、DebuggerTypeProxyAttribute 属性を使用します。DebuggerTypeProxyAttribute 属性は、型の表示プロキシを指定して、開発者が型のビューを調整できるようにする場合に使用します。DebuggerDisplayAttribute と同様に、この属性はアセンブリ レベルで使用できます。その場合、Target プロパティで、プロキシを使用する型を指定します。この属性は、その適用先の型内で発生する入れ子にされたプライベート型を指定するために使用することをお勧めします。型ビューアをサポートする式エバリュエータは、型を表示するときにこの属性をチェックします。この属性が確認された場合、式エバリュエータは、属性が適用されている型の代わりに表示プロキシ型を使用します。
DebuggerTypeProxyAttribute が存在する場合、デバッガの変数ウィンドウには、プロキシ型のパブリック メンバのみが表示されます。プライベート メンバは表示されません。データ ウィンドウの動作は、属性拡張ビューによって変更されません。
パフォーマンスへの不必要な影響を避けるために、表示プロキシの属性は、データ ウィンドウ内の型の横にある正符号 (+) をユーザーがクリックするか、または DebuggerBrowsableAttribute 属性を適用することによってオブジェクトが展開されるまで処理されません。そのため、表示型には属性を適用しないことをお勧めします。属性は表示型の本体内で適用できるようにします。
DebuggerTypeProxyAttribute を使用して、デバッガ表示プロキシとして使用する型を指定するコード例を次に示します。
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString =
"This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestStringProxy =
"This should appear in the debug window.";
// The constructor for the type proxy class must have a
// constructor that takes the target type as a parameter.
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
}
}
例
説明
次のコード例を Visual Studio 2005 で表示すると、DebuggerDisplayAttribute、DebuggerBrowsableAttribute、DebuggerTypeProxyAttribute の各属性の適用結果を確認できます。
コード
Imports System
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection
Class DebugViewTest
Shared Sub Main(ByVal args() As String)
Dim myHashTable As New MyHashtable()
myHashTable.Add("one", 1)
myHashTable.Add("two", 2)
Console.WriteLine(myHashTable.ToString())
Console.WriteLine("In Main.")
End Sub 'Main
End Class 'DebugViewTest
<DebuggerDisplay("{value}", Name := "{key}")> _
Friend Class KeyValuePairs
Private dictionary As IDictionary
Private key As Object
Private value As Object
Public Sub New(ByVal dictionary As IDictionary, ByVal key As Object, ByVal value As Object)
Me.value = value
Me.key = key
Me.dictionary = dictionary
End Sub 'New
End Class 'KeyValuePairs
<DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(GetType(MyHashtable.HashtableDebugView))> _
Class MyHashtable
Inherits Hashtable
Private Const TestString As String = "This should not appear in the debug window."
Friend Class HashtableDebugView
Private hashtable As Hashtable
Public Const TestString As String = "This should appear in the debug window."
Public Sub New(ByVal hashtable As Hashtable)
Me.hashtable = hashtable
End Sub 'New
End Class 'HashtableDebugView
End Class 'MyHashtable
using System;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
class DebugViewTest
{
// The following constant will appear in the debug window for DebugViewTest.
const string TabString = " ";
// The following DebuggerBrowsableAttribute prevents the property following it
// from appearing in the debug window for the class.
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";
static void Main(string[] args)
{
MyHashtable myHashTable = new MyHashtable();
myHashTable.Add("one", 1);
myHashTable.Add("two", 2);
Console.WriteLine(myHashTable.ToString());
Console.WriteLine("In Main.");
}
}
[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;
}
}
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
private const string TestString = "This should not appear in the debug window.";
internal class HashtableDebugView
{
private Hashtable hashtable;
public const string TestString = "This should appear in the debug window.";
public HashtableDebugView(Hashtable hashtable)
{
this.hashtable = hashtable;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePairs[] Keys
{
get
{
KeyValuePairs[] keys = new KeyValuePairs[hashtable.Count];
int i = 0;
foreach(object key in hashtable.Keys)
{
keys[i] = new KeyValuePairs(hashtable, key, hashtable[key]);
i++;
}
return keys;
}
}
}
}