Bagikan melalui


Meningkatkan Debugging dengan Atribut Tampilan Debugger

Catatan

Artikel ini khusus untuk .NET Framework. Ini tidak berlaku untuk implementasi .NET yang lebih baru, termasuk .NET 6 dan versi yang lebih baru.

Atribut tampilan debugger memungkinkan pengembang jenis, yang menentukan dan paling memahami perilaku runtime dari jenis tersebut, untuk juga menentukan seperti apa jenis itu ketika ditampilkan dalam debugger. Selain itu, atribut tampilan debugger yang menyediakan properti Targetdapat diterapkan pada tingkat assembly oleh pengguna tanpa mengetahui kode sumber. Atribut DebuggerDisplayAttribute mengontrol bagaimana jenis atau anggota ditampilkan di jendela variabel debugger. Atribut DebuggerBrowsableAttribute menentukan apakah dan bagaimana bidang atau properti ditampilkan di jendela variabel debugger. Atribut DebuggerTypeProxyAttribute menentukan jenis pengganti, atau proksi, untuk jenis dan mengubah cara jenis ditampilkan di jendela debugger. Saat Anda melihat variabel yang memiliki proksi, atau jenis pengganti, proksi berdiri untuk jenis asli di jendela tampilan debugger. Jendela variabel debugger hanya menampilkan anggota publik dari jenis proksi. Anggota privat tidak ditampilkan.

Menggunakan DebuggerDisplayAttribute

Konstruktor DebuggerDisplayAttribute memiliki argumen tunggal, string yang akan ditampilkan di kolom nilai untuk instans jenis. String ini dapat berisi kurung kurawal ({ dan }). Teks dalam sepasang kurung kurawal dievaluasi sebagai ekspresi. Misalnya, kode C# berikut menyebabkan "Hitungan = 4" ditampilkan ketika tanda plus (+) dipilih untuk memperluas tampilan debugger untuk instans MyHashtable.

[DebuggerDisplay("Count = {count}")]
class MyHashtable
{
    public int count = 4;
}

Atribut yang diterapkan ke properti yang direferensikan dalam ekspresi tidak diproses. Untuk compiler C#, ekspresi umum diizinkan yang hanya memiliki akses implisit ke referensi ini untuk instans jenis target saat ini. Ekspresi terbatas; tidak ada akses ke alias, lokal, atau penunjuk. Dalam kode C#, Anda dapat menggunakan ekspresi umum antara kurung kurawal yang memiliki akses implisit ke penunjuk this hanya untuk instans jenis target saat ini.

Misalnya, jika objek C# memiliki penimpaan ToString(), debugger akan memanggil penimpaan dan menunjukkan hasilnya alih-alih standar {<typeName>}. Dengan demikian, jika Anda telah menimpa ToString(), Anda tidak perlu menggunakan DebuggerDisplayAttribute. Jika Anda menggunakan keduanya, atribut DebuggerDisplayAttribute lebih diutamakan daripada ToString() penimpaan.

Menggunakan DebuggerBrowsableAttribute

Terapkan ke DebuggerBrowsableAttribute bidang atau properti untuk menentukan bagaimana bidang atau properti akan ditampilkan di jendela debugger. Konstruktor untuk atribut ini mengambil salah satu DebuggerBrowsableState nilai enumerasi, yang menentukan salah satu status berikut:

  • Never menunjukkan bahwa anggota tidak ditampilkan di jendela data. Misalnya, menggunakan nilai ini untuk DebuggerBrowsableAttribute bidang menghapus bidang dari hierarki; bidang tidak ditampilkan saat Anda memperluas jenis penutup dengan mengeklik tanda plus (+) untuk instans jenis.

  • Collapsed menunjukkan bahwa anggota ditampilkan tetapi tidak diperluas secara default. Ini adalah perilaku default.

  • RootHidden menunjukkan bahwa anggota itu sendiri tidak ditampilkan, tetapi objek konstituennya ditampilkan jika merupakan array atau koleksi.

Catatan

DebuggerBrowsableAttribute tidak didukung oleh Visual Basic di .NET Framework versi 2.0.

Contoh kode berikut menunjukkan penggunaan DebuggerBrowsableAttribute untuk mencegah properti mengikutinya muncul di jendela debug untuk kelas.

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
public static string y = "Test String";

Menggunakan DebuggerTypeProxy

Gunakan atribut DebuggerTypeProxyAttribute saat Anda perlu mengubah tampilan debugging tipe secara signifikan dan mendasar, tetapi tidak mengubah jenis itu sendiri. Atribut DebuggerTypeProxyAttribute digunakan untuk menentukan proksi tampilan untuk jenis, memungkinkan pengembang menyesuaikan tampilan untuk jenis tersebut. Atribut ini, seperti DebuggerDisplayAttribute, dapat digunakan pada tingkat assembl, dalam hal ini properti Target menentukan jenis yang proksinya akan digunakan. Penggunaan yang disarankan adalah bahwa atribut ini menentukan jenis berlapis privat yang terjadi dalam jenis saat atribut diterapkan. Evaluator ekspresi yang mendukung jenis penampil memeriksa atribut ini saat jenis ditampilkan. Jika atribut ditemukan, evaluator ekspresi menggantikan jenis proksi tampilan untuk jenis atribut yang diterapkan.

Jika DebuggerTypeProxyAttribute ada, jendela variabel debugger hanya menampilkan anggota publik dari jenis proxy. Anggota privat tidak ditampilkan. Perilaku jendela data tidak diubah oleh tampilan yang ditingkatkan atributnya.

Untuk menghindari penalti performa yang tidak perlu, atribut proksi tampilan tidak diproses sampai objek diperluas, baik melalui pengguna yang mengeklik tanda plus (+) di samping jenis di jendela data, atau melalui aplikasi atribut DebuggerBrowsableAttribute. Oleh karena itu, disarankan agar tidak ada atribut yang diterapkan ke jenis tampilan. Atribut dapat dan harus digunakan dalam isi jenis tampilan.

Contoh kode berikut menunjukkan penggunaan DebuggerTypeProxyAttribute untuk menentukan jenis yang akan digunakan sebagai proksi tampilan debugger.

[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;
        }
    }
}

Contoh

Deskripsi

Contoh kode berikut dapat dilihat di Visual Studio untuk melihat hasil penerapan atribut DebuggerDisplayAttribute, DebuggerBrowsableAttribute, dan DebuggerTypeProxyAttribute.

Kode


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

Lihat juga