Freigeben über


Verwenden des DebuggerDisplay-Attributs

Das DebuggerDisplay-Attribut (System.Diagnostics.DebuggerDisplayAttribute) steuert die Anzeige einer Klasse oder eines Felds in den Debuggervariablenfenstern.Mögliche Zuweisungen dieses Attributs:

  • Klassen

  • Strukturen

  • Delegaten

  • Enumerationen

  • Felder

  • Eigenschaften

  • Assemblys

Das DebuggerDisplay-Attribut verfügt über ein einziges Argument, das als Zeichenfolge in der Spalte Wert für Instanzen des Typs angezeigt wird Diese Zeichenfolge kann Klammern ({ und }) enthalten.Text innerhalb eines Paares geschweifter Klammern wird als ein Feld, eine Eigenschaft oder eine Methode ausgewertet.

Wenn bei einem C#-Objekt ToString() überschrieben wurde, ruft der Debugger die Überschreibung auf und zeigt deren Ergebnisse anstelle des Standardwerts {<typeName>} an.Wenn Sie also ToString() überschrieben haben, müssen Sie DebuggerDisplay nicht verwenden.Wenn Sie beides verwenden, hat das DebuggerDisplay-Attribut Vorrang gegenüber der ToString()-Überschreibung.

Ob der Debugger diesen impliziten ToString() -Aufruf auswertet, hängt von einer Benutzereinstellung im Dialogfeld Optionen ab (Kategorie Debuggen, Seite Allgemein).Visual Basic implementiert diese implizite ToString()-Auswertung nicht.

Wichtiger HinweisWichtig

Wenn das Kontrollkästchen Unformatierte Struktur von Objekten in Variablenfenstern anzeigen im Dialogfeld Extras/Optionen aktiviert ist, wird das DebuggerDisplay-Attribut ignoriert.

In der folgenden Tabelle werden einige Verwendungsmöglichkeiten des DebuggerDisplay-Attributs sowie Beispielausgaben gezeigt.

Attribut

Ausgabe (angezeigt in der Spalte Wert)

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

Angewendet auf einen Typ mit den Feldern x und y.

x = 5 y = 18

[DebuggerDisplay("String value is {getString()}")]Die Parametersyntax kann je nach Sprache unterschiedlich sein.Achten Sie deshalb besonders auf die Syntax.

String value is [5, 6, 6]

DebuggerDisplay kann auch benannte Parameter akzeptieren.

Parameter

Zweck

Name, Type

Diese Parameter beeinflussen die Spalte Name und die Spalte Typ der Variablenfenster.(Sie können in Zeichenfolgen mit der gleichen Syntax wie der Konstruktor festgelegt werden.), können das Überbeanspruchen dieser Parameter oder sie falsch verwenden, die zu Verwirrung führen ausgeben.

Target, TargetTypeName

Gibt den Zieltyp an, wenn das Attribut auf Assemblyebene verwendet wird.

HinweisHinweis

Die Datei autoexp.cs verwendet das DebuggerDisplay-Attribut auf Assemblyebene.Die Datei autoexp.cs bestimmt die Standarderweiterungen, die Visual Studio für C#-Variablen verwendet.Suchen Sie in der Datei autoexp.cs entweder Beispiele zur Verwendung des DebuggerDisplay-Attributs, oder bearbeiten und kompilieren Sie die Datei autoexp.cs, um die Standarderweiterungen zu ändern.Erstellen Sie eine Sicherungskopie der Datei autoexp.cs, bevor Sie sie ändern.Sie müssen auf die Datei "Microsoft.VisualStudio.DebuggerVisualizers.dll" in "\Programme\Microsoft Visual Studio 11.0-\Common7\IDE\PublicAssemblies" verweisen.Die Datei "autoexp.cs" finden Sie im Verzeichnis "Meine Dokumente/Visual Studio 2012/Visualizers".

Verwenden von Ausdrücken in DebuggerDisplay

Obwohl ein allgemeiner Ausdruck zwischen den geschweiften Klammern in einem DebuggerDisplay-Attribut verwendet werden kann, wird diese Vorgehensweise nicht empfohlen.

Ein allgemeiner Ausdruck in DebuggerDisplay verfügt über impliziten Zugriff auf den this-Zeiger nur für die aktuelle Instanz des Zieltyps.Der Ausdruck hat keinen Zugriff auf Aliase, lokale Variablen oder Zeiger.Wenn der Ausdruck auf Eigenschaften verweist, werden deren Attribute nicht verarbeitet.Beispielsweise würde der C#-Code [DebuggerDisplay("Object {count - 2}" den Wert Object 6 anzeigen, wenn das Feld count 8 wäre.

Verwenden von Ausdrücken in DebuggerDisplay kann zu folgenden Problemen führen:

  • Das Auswerten von Ausdrücken ist der aufwändigste Vorgang im Debugger, und der Ausdruck wird bei jedem Anzeigen ausgewertet.Dies kann Leistungsprobleme verursachen, während der Code schrittweise durchlaufen wird.Beispielsweise kann ein komplexer Ausdruck, der zum Anzeigen der Werte in einer Auflistung oder Liste verwendet wird, sehr langsam sein, wenn die Anzahl der Elemente groß ist.

  • Ausdrücke werden von der Ausdrucksauswertung der Sprache des aktuellen Stapelrahmens und nicht von der Auswertung der Sprache ausgewertet, in der der Ausdruck geschrieben wurde.Dies kann unvorhersehbare Ergebnisse zur Folge haben, wenn die Sprachen unterschiedlich sind.

  • Durch Auswerten eines Ausdrucks kann der Zustand der Anwendung geändert werden.Beispielsweise ändert ein Ausdruck, der den Wert einer Eigenschaft festlegt, den Eigenschaftswert im ausgeführten Code.

Eine Möglichkeit, die möglichen Probleme der Ausdrucksauswertung zu verringern, ist das Erstellen einer privaten Eigenschaft, die den Vorgang ausführt und eine Zeichenfolge zurückgibt.Das DebuggerDisplay-Attribut kann dann den Wert dieser privaten Eigenschaft anzeigen.Im folgenden Beispiel wird dieses Muster implementiert:

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

Beispiel

Im folgenden Codebeispiel wird veranschaulicht, wie DebuggerDisplay zusammen mit DebuggerBrowseable und DebuggerTypeProxy verwendet wird.Bei der Anzeige in einem Debuggervariablenfenster (z. B. im Fenster Überwachen) wird dadurch eine Erweiterung produziert, die folgendermaßen aussieht:

Name

Wert

Text [Type]

Schlüssel

"three"

object {string}

Wert

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

Siehe auch

Referenz

Verwenden des DebuggerTypeProxy-Attributs

Konzepte

Anzeigen von benutzerdefinierten Datentypen

Verbessern des Debuggens mit den Debuggeranzeigeattributen