Indicare al debugger cosa visualizzare usando l'attributo DebuggerDisplay (C#, Visual Basic, F #, C++/CLI)Tell the debugger what to show using the DebuggerDisplay Attribute (C#, Visual Basic, F#, C++/CLI)

DebuggerDisplayAttribute controlla la modalità di visualizzazione di un oggetto, una proprietà o un campo nelle finestre delle variabili del debugger.The DebuggerDisplayAttribute controls how an object, property, or field is displayed in the debugger variable windows. Questo attributo può essere applicato a tipi, delegati, proprietà, campi e assembly.This attribute can be applied to types, delegates, properties, fields, and assemblies. Se applicato a un tipo di base, l'attributo si applica anche a una sottoclasse.If applied to a base type, the attribute also applies to a subclass.

L'attributo DebuggerDisplay presenta un solo argomento, costituito da una stringa da visualizzare nella colonna del valore per le istanze del tipo.The DebuggerDisplay attribute has a single argument, which is a string to be displayed in the value column for instances of the type. Questa stringa può contenere parentesi graffe ({ e }).This string can contain braces ({ and }). Il testo racchiuso tra due parentesi graffe viene valutato come un campo, una proprietà o un metodo.Text within a pair of braces is evaluated as a field, property or method.

Se una classe dispone di un metodo ToString() sottoposto a override, il debugger usa il metodo sottoposto a override anziché il valore {<typeName>}predefinito.If a class has an overridden ToString() method, the debugger uses the overridden method instead of the default {<typeName>}. Pertanto, se è stato eseguito l'override del metodo ToString() , il debugger usa il metodo sottoposto a override anziché il valore{<typeName>}predefinito e non è necessario usare DebuggerDisplay.Thus, if you have overridden the ToString() method, the debugger uses the overridden method instead of the default{<typeName>}, and you do not have to use DebuggerDisplay. Se si usano entrambi, l'attributo DebuggerDisplay avrà la precedenza sul metodo ToString() sottoposto a override.If you use both, the DebuggerDisplay attribute takes precedence over the overridden ToString() method. L' DebuggerDisplay attributo ha anche la precedenza sul metodo sottoposto ToString() a override in una sottoclasse.The DebuggerDisplay attribute also takes precedence over the overridden ToString() method in a subclass.

Il fatto che il debugger valuti questa ToString() chiamata implicita dipende da un'impostazione utente nella finestra di dialogo strumenti/opzioni/debug .Whether the debugger evaluates this implicit ToString() call depends on a user setting in the Tools / Options / Debugging dialog box.

Importante

Se la casella di controllo Mostra struttura non elaborata degli oggetti nelle finestre delle variabili è selezionata nella finestra di dialogo strumenti/opzioni/debug , l' DebuggerDisplay attributo viene ignorato.If the Show raw structure of objects in variables windows check box is selected in the Tools / Options / Debugging dialog box, then the DebuggerDisplay attribute is ignored.

Nota

Per il codice nativo, questo attributo è supportato solo nel codice C++/CLI.For native code, this attribute is supported only in C++/CLI code.

Nella tabella riportata di seguito vengono visualizzati alcuni utilizzi possibili dell'attributo DebuggerDisplay e alcuni output di esempio.The following table shows some possible uses of the DebuggerDisplay attribute and example outputs.

AttributoAttribute Output visualizzato nella colonna ValoreOutput appearing in the Value column
[DebuggerDisplay("x = {x} y = {y}")]

Utilizzato in un tipo con campi x e y.Used on a type with fields x and y.
x = 5 y = 18
[DebuggerDisplay("String value is {getString()}")]La sintassi del parametro può variare a seconda del linguaggio.[DebuggerDisplay("String value is {getString()}")]Parameter syntax can vary between languages. Prestare, pertanto, particolare attenzione.Therefore, use it with care. String value is [5, 6, 6]

DebuggerDisplay può anche accettare parametri denominati.DebuggerDisplay can also accept named parameters.

ParametriParameters ScopoPurpose
Name, TypeName, Type Questi parametri influiscono sulle colonne Nome e Tipo delle finestre delle variabili.These parameters affect the Name and Type columns of the variable windows. Possono essere impostati su stringhe utilizzando la stessa sintassi del costruttore. L'utilizzo eccessivo o errato di questi parametri può generare output poco chiaro.(They can be set to strings using the same syntax as the constructor.)Overusing these parameters, or using them incorrectly, can cause confusing output.
Target, TargetTypeNameTarget, TargetTypeName Specifica il tipo di destinazione quando l'attributo viene utilizzato a livello di assembly.Specifies the target type when the attribute is used at the assembly level.

Il file autoexp.cs usa l'attributo DebuggerDisplay a livello di assembly.The autoexp.cs file uses the DebuggerDisplay attribute at the assembly level. Il file autoexp.cs determina le espansioni predefinite usate da Visual Studio per gli oggetti .NET.The autoexp.cs file determines the default expansions that Visual Studio uses for .NET objects. Esaminare il file autoexp.cs per esempi di utilizzo dell'attributo DebuggerDisplay oppure modificare e compilare il file autoexp.cs per modificare le espansioni predefinite.You can examine the autoexp.cs file for examples of how to use the DebuggerDisplay attribute, or you can modify and compile the autoexp.cs file to change the default expansions. Assicurarsi di eseguire il backup del file autoexp.cs prima di modificarlo.Be sure to back up the autoexp.cs file before you modify it.

Per compilare autoexp.cs, aprire un prompt dei comandi per gli sviluppatori per VS2015 ed eseguire i comandi seguenti.To build autoexp.cs, open up a Developer Command Prompt for VS2015, and run the following commands

cd <directory containing autoexp.cs>
csc /t:library autoexp.cs

Le modifiche apportate ad autoexp.dll verranno rilevate nella sessione di debug successiva.The changes to autoexp.dll will be picked up in the next debug session.

Utilizzo di espressioni in DebuggerDisplayUsing Expressions in DebuggerDisplay

Sebbene sia possibile utilizzare un'espressione generale tra parentesi graffe in un attributo DebuggerDisplay, questa procedura non è consigliata.Although you can use a general expression between the braces in a DebuggerDisplay attribute, this practice is not recommended.

Un'espressione generale in DebuggerDisplay ha accesso implicito al puntatore this solo per l'istanza corrente del tipo di destinazione.A general expression in DebuggerDisplay has implicit access to the this pointer for the current instance of the target type only. L'espressione non ha accesso ad alias, variabili locali o puntatori.The expression has no access to aliases, locals, or pointers. Se l'espressione fa riferimento a delle proprietà, gli attributi su tali proprietà non vengono elaborati.If the expression references properties, attributes on those properties are not processed. Ad esempio, il codice C# [DebuggerDisplay("Object {count - 2}")] visualizza Object 6 se il campo count è 8.For example, the C# code [DebuggerDisplay("Object {count - 2}")] would display Object 6 if the field count was 8.

L'utilizzo di espressioni in DebuggerDisplay può causare i problemi seguenti:Using expressions in DebuggerDisplay can lead to the following issues:

  • La valutazione delle espressioni è l'operazione più dispendiosa nel debugger e viene valutata ogni volta che viene visualizzata.Evaluating expressions is the most expensive operation in the debugger and the expression is evaluated each time it is displayed. Ciò può causare problemi relativi alle prestazioni nell'esecuzione del codice istruzione per istruzione.This can cause performance issues in stepping through code. Ad esempio, un'espressione complessa che viene utilizzata per visualizzare i valori in una raccolta o in un elenco può essere molto lenta quando è presente un grande numero di elementi.For example, a complex expression that is used to display the values in a collection or list can be very slow when the number of elements is large.

  • Le espressioni vengono valutate dall'analizzatore di espressioni del linguaggio dello stack frame corrente, non dall'analizzatore del linguaggio in cui l'espressione è stata scritta.Expressions are evaluated by the expression evaluator of the language of the current stack frame and not by the evaluator of the language in which the expression was written. Questa situazione può provocare risultati imprevisti quando i linguaggi sono diversi.This can cause unpredictable results when the languages are different.

  • La valutazione di un'espressione può modificare lo stato dell'applicazione.Evaluating an expression can change the state of the application. Ad esempio, un'espressione che imposta il valore di una proprietà modifica il valore della proprietà nel codice in esecuzione.For example, an expression that sets the value of a property mutates the property value in the executing code.

    Per ridurre i possibili problemi della valutazione dell'espressione, è possibile creare una proprietà privata che esegue l'operazione e restituisce una stringa.One way to reduce the possible problems of expression evaluation is by creating a private property that performs the operation and returns a string. L'attributo DebuggerDisplay può quindi visualizzare il valore di tale proprietà privata.The DebuggerDisplay attribute can then display the value of that private property. Nell'esempio seguente viene implementato questo modello:The following example implements this pattern:

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

Il suffisso ", NQ" indica all'analizzatore di espressioni di rimuovere le virgolette quando viene visualizzato il valore finale (NQ = nessuna virgoletta).The ",nq" suffix tells the expression evaluator to remove the quotes when displaying the final value (nq = no quotes).

EsempioExample

Nell'esempio di codice seguente viene illustrato l'utilizzo di DebuggerDisplay, insieme a DebuggerBrowseable e DebuggerTypeProxy.The following code example shows how to use DebuggerDisplay, together with DebuggerBrowseable and DebuggerTypeProxy. Quando è visualizzato in una finestra delle variabili del debugger, come la finestra Espressioni di controllo , produce un'espansione analoga alla seguente:When viewed in a debugger variables window, such as the Watch window, it produces an expansion that looks like this:

NomeName ValoreValue TipoType
ChiaveKey "three""three" oggetto {string}object {string}
ValoreValue 33 oggetto {int}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;
            }
        }
    }
}

Vedere ancheSee also