次の方法で共有


デバッガー表示属性を使用したデバッグの強化

この記事は .NET Framework に固有のものです。 .NET 6 以降のバージョンを含む、.NET の新しい実装には適用されません。

デバッガーの表示属性を使用すると、その型を開発した開発者は、その型のランタイム動作をもっとも理解した上で、デバッガーに表示される際のその型の外観を指定できます。 さらに、 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 バージョン 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 で表示して、 DebuggerDisplayAttributeDebuggerBrowsableAttribute、および DebuggerTypeProxyAttribute 属性を適用した結果を確認できます。

コード


using namespace System;
using namespace System::Collections;
using namespace System::Diagnostics;
using namespace System::Reflection;

ref class HashtableDebugView;

[DebuggerDisplay("{value}", Name = "{key}")]
ref class KeyValuePairs
{
private:
    IDictionary^ dictionary;
    Object^ key;
    Object^ value;

public:
    KeyValuePairs(IDictionary^ dictionary, Object^ key, Object^ value)
    {
        this->value = value;
        this->key = key;
        this->dictionary = dictionary;
    }
};

[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(HashtableDebugView::typeid)]
ref class MyHashtable : Hashtable
{
private:
    static const String^ TestString = "This should not appear in the debug window.";

internal:
    ref class HashtableDebugView
    {
    private:
        Hashtable^ hashtable;
    public:
        static const String^ TestString = "This should appear in the debug window.";
        HashtableDebugView(Hashtable^ hashtable)
        {
            this->hashtable = hashtable;
        }

        [DebuggerBrowsable(DebuggerBrowsableState::RootHidden)]
        property array<KeyValuePairs^>^ Keys
        {
            array<KeyValuePairs^>^ get()
            {
                array<KeyValuePairs^>^ keys = gcnew array<KeyValuePairs^>(hashtable->Count);

                IEnumerator^ ie = hashtable->Keys->GetEnumerator();
                int i = 0;
                Object^ key;
                while (ie->MoveNext())
                {
                    key = ie->Current;
                    keys[i] = gcnew KeyValuePairs(hashtable, key, hashtable[key]);
                    i++;
                }
                return keys;
            }
        }
    };
};

public ref class DebugViewTest
{
private:
    // The following constant will appear in the debug window for DebugViewTest.
    static const String^ TabString = "    ";
public:
    // The following DebuggerBrowsableAttribute prevents the property following it
    // from appearing in the debug window for the class.
    [DebuggerBrowsable(DebuggerBrowsableState::Never)]
    static String^ y = "Test String";

    static void Main()
    {
        MyHashtable^ myHashTable = gcnew MyHashtable();
        myHashTable->Add("one", 1);
        myHashTable->Add("two", 2);
        Console::WriteLine(myHashTable->ToString());
        Console::WriteLine("In Main.");
    }
};

int main()
{
    DebugViewTest::Main();
}
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()
    {
        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;
            }
        }
    }
}
Imports System.Collections
Imports System.Diagnostics
Imports System.Reflection



Class DebugViewTest
    ' The following constant will appear in the debug window for DebugViewTest.
    Const TabString As String = "    "
    ' The following DebuggerBrowsableAttribute prevents the property following it
    ' from appearing in the debug window for the class.
    <DebuggerBrowsable(DebuggerBrowsableState.Never)> _
    Public Shared y As String = "Test String"

    Shared Sub Main()
        Dim myHashTable As New MyHashtable()
        myHashTable.Add("one", 1)
        myHashTable.Add("two", 2)
        Console.WriteLine(myHashTable.ToString())
        Console.WriteLine("In Main.")

    End Sub
End Class
<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
End Class
<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 Shared TestString As String = "This should appear in the debug window."

        Public Sub New(ByVal hashtable As Hashtable)
            Me.hashtable = hashtable
        End Sub

        <DebuggerBrowsable(DebuggerBrowsableState.RootHidden)> _
        ReadOnly Property Keys as KeyValuePairs()
            Get
                Dim nkeys(hashtable.Count - 1) As KeyValuePairs

                Dim i as Integer = 0
                For Each key As Object In hashtable.Keys
                    nkeys(i) = New KeyValuePairs(hashtable, key, hashtable(key))
                    i = i + 1
                Next
                Return nkeys
            End Get
        End Property

    End Class
End Class

こちらも参照ください