Share via


Usando o atributo DebuggerDisplay

O atributo DebuggerDisplay (System.Diagnostics.DebuggerDisplayAttribute) controla como uma classe ou um campo são exibidos nas janelas da variável do depurador. Esse atributo poderá ser aplicado a:

  • Classes

  • Structs

  • Representantes

  • Enums

  • Campos

  • Propriedades

  • Assemblies

O atributo DebuggerDisplay tem um único argumento, que é uma cadeia de caracteres a ser exibida na coluna de valor para instâncias do tipo. Essa cadeia de caracteres pode conter chaves ({ e }). O texto dentro de um par de chaves será avaliado como um campo, propriedade ou método.

Se um objeto C# tiver um ToString() substituído, o depurador chamará a substituição e mostrará seu resultado em vez do {<typeName>} padrão. Portanto, se você substituiu ToString(), não terá que usar DebuggerDisplay. Se você usar ambas, o atributo DebuggerDisplay terá precedência sobre a substituição de ToString().

Se o depurador avalia essa chamada de ToString() implícita depende de uma configuração de usuário na caixa de diálogo Opções (categoria Depuração, página Geral). O Visual Basic não implementa esta avaliação de ToString() implícita.

Importante

Se a caixa de seleção Mostrar estrutura bruta de objetos nas janelas de variáveis estiver selecionada na caixa de diálogo Opções de Ferramentas, o atributo DebuggerDisplay será ignorado.

A tabela a seguir mostra alguns usos possíveis do atributo DebuggerDisplay e saídas de exemplo.

Atributo

A saída aparecendo na coluna Valor)

[DebuggerDisplay("x = {x} y = {y}")]

Usado em um tipo com campos x e y.

x = 5 y = 18

A sintaxe do parâmetro [DebuggerDisplay("String value is {getString()}")]pode variar entre linguagens. Em virtude disso, use com cuidado.

String value is [5, 6, 6]

DebuggerDisplay também pode aceitar parâmetros nomeados.

Parâmetros

Finalidade

Name, Type

Esses parâmetros afetam as colunas Nome e Tipo das janelas variáveis. (Podem ser definidos como cadeias de caracteres usando a mesma sintaxe que o construtor.) Usar esses parâmetros demais ou usá-los incorretamente pode causar uma saída confusa.

Target, TargetTypeName

Especifica o tipo de destino quando o atributo é usado no nível de assembly.

Dica

O arquivo autoexp.cs usa o atributo DebuggerDisplay no nível de assembly.O arquivo autoexp.cs determina as expansões padrão que o Visual Studio usa para variáveis C#.Você pode examinar o arquivo autoexp.cs para obter exemplos de como usar o atributo DebuggerDisplay ou pode modificar e compilar o arquivo autoexp.cs para alterar as expansões padrão.Faça backup do arquivo autoexp.cs antes de modificá-lo.Você deve fazer referência a Microsoft.VisualStudio.DebuggerVisualizers.dll em \Arquivos de Programas\Microsoft Visual Studio 12.0\Common7\IDE\PublicAssemblies.Você pode localizar o arquivo autoexp.cs em Meus Documentos/Visual Studio 2012/Visualizers.

Usando expressões em DebuggerDisplay

Embora você possa usar uma expressão geral entre as chaves em um atributo DebuggerDisplay, esta prática não é recomendada.

Uma expressão geral em DebuggerDisplay tem acesso implícito ao ponteiro this somente para a instância atual do tipo de destino. A expressão não tem acesso a alias, locais ou ponteiros. Se a expressão fizer referência a propriedades, os atributos nessas propriedades não serão processados. Por exemplo, o código C# [DebuggerDisplay("Object {count - 2}" exibiria Object 6 se o campo count fosse 8.

Usar expressões em DebuggerDisplay pode resultar nos seguintes problemas:

  • Avaliar expressões é a operação mais cara no depurador e a expressão é avaliada toda vez que é exibida. Isso pode causar problemas de desempenho ao depurar o código. Por exemplo, uma expressão complexa que é usada para exibir os valores em uma coleção ou lista poderá ser muito lenta quando o número de elementos for grande.

  • As expressões são avaliadas pelo avaliador de expressão da linguagem do quadro de pilhas atual e não pelo avaliador da linguagem na qual a expressão foi gravada. Isso pode causar resultados imprevisíveis quando as linguagens são diferentes.

  • Avaliar uma expressão pode alterar o estado do aplicativo. Por exemplo, uma expressão que define o valor de uma propriedade transforma o valor da propriedade no código de execução.

Uma maneira de reduzir os possíveis problemas de avaliação da expressão é criando uma propriedade privada que executa a operação e retorna uma cadeia de caracteres. O atributo DebuggerDisplay pode em seguida exibir o valor dessa propriedade privada. O exemplo a seguir implementa esse padrão:

[DebuggerDisplay("{DebuggerDisplay,nq}")]public sealed class MyClass {    public int count { get; set; }    public bool flag { get; set; }    private string DebuggerDisplay {        get{ return string.Format("("Object {0}", count - 2); }    }}

Exemplo

O exemplo de código a seguir mostra como usar DebuggerDisplay junto com DebuggerBrowseable e DebuggerTypeProxy. Quando exibido em uma janela variáveis de depurador, como, por exemplo, a janela Inspeção, ele produz uma expansão semelhante ao seguinte:

Nome

Valor

Tipo

Key

"three"

object {string}

Valor

3

object {int}

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

    public object Key
    {
        get { return key; }
        set
        {
            object tempValue = dictionary[key];
            dictionary.Remove(key);
            key = value;
            dictionary.Add(key, tempValue);
        }
    }

    public object Value
    {
        get { return this.value; }
        set
        {
            this.value = value;
            dictionary[key] = this.value;
        }
    }
}

[DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable
{
    public Hashtable hashtable;

    public MyHashtable()
    {
        hashtable = new Hashtable();  
    }    private string DebuggerDisplay    {        get { return "Count = " + hashtable.Count); }    }

    private class HashtableDebugView
    {
        private MyHashtable myhashtable;
        public HashtableDebugView(MyHashtable myhashtable)
        {
            this.myhashtable = myhashtable;
        }

        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public KeyValuePairs[] Keys
        {
            get
            {
                KeyValuePairs[] keys = new KeyValuePairs[myhashtable.hashtable.Count];

                int i = 0;
                foreach (object key in myhashtable.hashtable.Keys)
                {
                    keys[i] = new KeyValuePairs(myhashtable.hashtable, key, myhashtable.hashtable[key]);
                    i++;
                }
                return keys;
            }
        }
    }
}

Consulte também

Referência

Usando o atributo DebuggerTypeProxy

Conceitos

Exibindo tipos de dados personalizados

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