Partilhar via


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

Atributos de exibição do depurador permitem que o desenvolvedor do tipo, que especifica e melhor entende o comportamento do runtime desse tipo, também especificar o que esse tipo de aparência quando ele for exibido em um depurador. Além disso, o depurador exibir atributos que fornecem uma Target propriedade pode ser aplicada no nível do assembly por usuários sem conhecimento do código fonte. O DebuggerDisplayAttribute controles de atributo, como um tipo ou membro é exibido no windows de variável de depurador. O DebuggerBrowsableAttribute atributo determina se e como um campo ou propriedade é exibida no windows de variável de depurador. O DebuggerTypeProxyAttribute atributo especifica um tipo de substituto, ou um proxy, para um tipo e alterações a maneira de como o tipo é exibida no depurador do windows. Quando você visualiza uma variável que possui um proxy ou o tipo de substituição, o proxy significa o tipo original na janela de exibição do depurador**.** A janela do depurador de variável exibe somente os membros do tipo de proxy público. Membros particulares não são exibidos.

Usando o DebuggerDisplayAttribute.

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

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

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

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

Usando o DebuggerBrowsableAttribute.

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

  • Neverindica que o membro não é exibido na janela de dados. Por exemplo, usando esse valor para o DebuggerBrowsableAttribute em um campo remove o campo da hierarquia; o campo não é exibido quando você expande o tipo de delimitador clicando no sinal de mais (+) para a instância do tipo.

  • Collapsedindica que o membro é exibido, mas não expandido por padrão. Esse é o comportamento padrão.

  • RootHiddenindica que o próprio membro não for mostrado, mas seus objetos constituintes são exibidos se for uma matriz ou coleção.

Observação

O não há suporte paraDebuggerBrowsableAttribute de Visual Basic na.NET Framework versão 2.0.

O exemplo de código a seguir mostra o uso da DebuggerBrowsableAttribute para impedir que a propriedade após ele 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 Quando você precisar alterar o modo de depuração de um tipo de significativamente e fundamentalmente, mas não alterar o próprio tipo de atributo. O DebuggerTypeProxyAttribute atributo é usado para especificar um proxy de exibição para um tipo, permitindo que um desenvolvedor adaptar o modo de exibição para o tipo. Esse atributo, como o DebuggerDisplayAttribute, pode ser usado no nível do assembly, caso em que o Target propriedade especifica o tipo para o qual o proxy será usado. O uso recomendado é que este atributo especifica um tipo aninhado particular que ocorre dentro do tipo ao qual o atributo é aplicado. Um avaliador de expressão que suporta digite visualizadores verifica para este atributo quando um tipo é exibido. Se o atributo for encontrado, o avaliador da expressão substitui o tipo de proxy para o atributo é aplicado para o tipo de exibição.

Quando o DebuggerTypeProxyAttribute estiver presente, a janela depurador de variável exibe somente os membros públicos do tipo de proxy. Membros particulares não são exibidos. O comportamento da janela de dados não é alterado por modos de exibição avançado de atributo.

Para evitar penalidades de desempenho desnecessária, atributos de proxy de exibição não são processados até que o objeto é expandido por meio do usuário clicar no sinal de mais (+) próximo ao tipo de em uma janela de dados ou por meio da aplicação do DebuggerBrowsableAttribute atributo. Portanto, é recomendável que nenhum atributo seja aplicado ao tipo de exibição. Atributos podem e devem ser aplicados dentro do corpo do tipo de exibição.

O exemplo de código a seguir mostra o uso de DebuggerTypeProxyAttribute para especificar um tipo a ser usado como um proxy de exibição do 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

Descrição

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

Código

Imports System
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 '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 Shared TestString As String = "This should appear in the debug window."

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

        <DebuggerBrowsable(DebuggerBrowsableState.RootHidden)> _
        ReadOnly Property Keys as KeyValuePairs()
            Get
                Dim nkeys(hashtable.Count) 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 '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()
    {
        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;
            }
        }
    }
}

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();
}

Consulte também

Referência

DebuggerDisplayAttribute

DebuggerBrowsableAttribute

DebuggerTypeProxyAttribute