Partilhar via


Aprimorando a depuração com os atributos de exibição do depurador

Nota

Este artigo é específico do .NET Framework. Ele não se aplica a implementações mais recentes do .NET, incluindo o .NET 6 e versões posteriores.

Os atributos de exibição do depurador permitem que o desenvolvedor do tipo, que especifica e melhor entende o comportamento de tempo de execução desse tipo, também especifique como será esse tipo quando for exibido em um depurador. Além disso, os atributos de exibição do depurador que fornecem uma Target propriedade podem ser aplicados no nível do assembly por usuários sem conhecimento do código-fonte. O DebuggerDisplayAttribute atributo controla como um tipo ou membro é exibido nas janelas de variáveis do depurador. O DebuggerBrowsableAttribute atributo determina se e como um campo ou propriedade é exibido nas janelas da variável do depurador. O DebuggerTypeProxyAttribute atributo especifica um tipo substituto, ou um proxy, para um tipo e altera a maneira como o tipo é exibido nas janelas do depurador. Quando você visualiza uma variável que tem um proxy ou tipo substituto, o proxy representa o tipo original na janela de exibição do depurador. A janela da variável do depurador exibe apenas os membros públicos do tipo de proxy. Membros privados não são exibidos.

Usando o DebuggerDisplayAttribute

O DebuggerDisplayAttribute construtor tem um único argumento: uma cadeia de caracteres a ser exibida na coluna value para instâncias do tipo. Esta cadeia de caracteres pode conter chaves ({ e }). O texto dentro de um par de chaves é avaliado como uma expressão. Por exemplo, o código C# a seguir faz com que "Count = 4" seja exibido quando o sinal de adição (+) é selecionado para expandir a exibição do depurador para uma instância de MyHashtable.

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

Os atributos aplicados às propriedades referenciadas na expressão não são processados. Para o compilador C#, é permitida uma expressão geral que tem apenas acesso implícito a essa referência para a instância atual do tipo de destino. A expressão é limitada; Não há acesso a aliases, locais ou ponteiros. No código C#, você pode usar uma expressão geral entre as chaves que tem acesso implícito ao this ponteiro apenas para a instância atual do tipo de destino.

Por exemplo, se um objeto C# tiver uma substituição ToString(), o depurador chamará a substituição e mostrará seu resultado em vez do padrão {<typeName>}. Assim, se você tiver substituído ToString(), você não precisa usar DebuggerDisplayAttribute. Se você usar ambos, o DebuggerDisplayAttribute atributo terá precedência sobre a ToString() substituição.

Usando o DebuggerBrowsableAttribute

Aplique o DebuggerBrowsableAttribute a um campo ou propriedade para especificar como o campo ou propriedade deve ser exibido na janela do depurador. O construtor para este atributo usa um dos valores de DebuggerBrowsableState enumeração, que especifica um dos seguintes estados:

  • Never Indica que o membro não é exibido na janela Dados. Por exemplo, usar esse valor para o DebuggerBrowsableAttribute em um campo remove o campo da hierarquia, o campo não é exibido quando você expande o tipo de inclusão clicando no sinal de adição (+) para a instância do tipo.

  • Collapsed Indica que o membro é exibido, mas não expandido por padrão. Este é o comportamento predefinido.

  • RootHidden Indica que o membro em si não é mostrado, mas seus objetos constituintes são exibidos se for uma matriz ou coleção.

Nota

O DebuggerBrowsableAttribute não é suportado pelo Visual Basic no .NET Framework versão 2.0.

O exemplo de código a seguir mostra o uso do DebuggerBrowsableAttribute para impedir que a propriedade que o segue apareça na janela de depuração para a classe.

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

Usando o DebuggerTypeProxy

Use o DebuggerTypeProxyAttribute atributo quando precisar alterar significativa e fundamentalmente a exibição de depuração de um tipo, mas não alterar o tipo em si. O DebuggerTypeProxyAttribute atributo é usado para especificar um proxy de exibição para um tipo, permitindo que um desenvolvedor adapte a exibição para o tipo. Esse atributo, como o DebuggerDisplayAttribute, pode ser usado no nível do assembly, caso em que a Target propriedade especifica o tipo para o qual o proxy será usado. O uso recomendado é que esse atributo especifique um tipo aninhado privado que ocorre dentro do tipo ao qual o atributo é aplicado. Um avaliador de expressão que suporta visualizadores de tipo verifica esse atributo quando um tipo é exibido. Se o atributo for encontrado, o avaliador de expressão substituirá o tipo de proxy de exibição pelo tipo ao qual o atributo é aplicado.

Quando o DebuggerTypeProxyAttribute está presente, a janela da variável do depurador exibe apenas os membros públicos do tipo de proxy. Membros privados não são exibidos. O comportamento da janela de dados não é alterado por exibições com atributos aprimorados.

Para evitar penalidades de desempenho desnecessárias, os atributos do proxy de exibição não são processados até que o objeto seja expandido, seja através do usuário clicando no sinal de adição (+) ao lado do tipo em uma janela de dados, ou através da aplicação do DebuggerBrowsableAttribute atributo. Portanto, recomenda-se que nenhum atributo seja aplicado ao tipo de exibição. Os atributos podem e devem ser aplicados dentro do corpo do tipo de exibição.

O exemplo de código a seguir mostra o uso do para especificar um tipo a ser usado como um proxy de exibição do DebuggerTypeProxyAttribute depurador.

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

Exemplo

Description

O exemplo de código a seguir pode ser exibido no Visual Studio para ver os resultados da aplicação DebuggerDisplayAttributedos atributos , DebuggerBrowsableAttribute, e DebuggerTypeProxyAttribute .

Código


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

Consulte também