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