Řekněte ladicímu programu, co se má zobrazit pomocí atributu DebuggerDisplay (C#, Visual Basic, F#, C++/CLI).

Určuje DebuggerDisplayAttribute , jak se objekt, vlastnost nebo pole zobrazí v oknech proměnných ladicího programu. Tento atribut lze použít u typů (třídy, struktury, výčty, delegáty). Pokud je použit u základního typu, atribut se vztahuje také na podtřídu.

Atribut DebuggerDisplay má jeden argument, což je řetězec, který se má zobrazit ve sloupci hodnoty pro instance typu. Tento řetězec může obsahovat složené závorky ({ a }). Text v rámci dvojice složených závorek se vyhodnotí jako pole, vlastnost nebo metoda.

Pokud třída má přepsánou ToString() metodu, ladicí program používá přepsánou metodu místo výchozí {<typeName>}. Proto, pokud jste přepsali metodu ToString() , ladicí program používá přepsánou metodu místo výchozího {<typeName>}a nemusíte používat DebuggerDisplay. Pokud použijete obojí, DebuggerDisplay má atribut přednost před přepsánou ToString() metodou. Atribut DebuggerDisplay má také přednost před přepsánou ToString() metodou v podtřídě.

Zda ladicí program vyhodnotí toto implicitní ToString() volání, závisí na uživatelském nastavení v dialogovém okně Nástroje / Možnosti / Ladění .

Důležité

Pokud je v dialogovém okně Nástroje / Možnosti / Ladění zaškrtnuté políčko Zobrazit nezpracovanou strukturu objektů v oknech proměnných, DebuggerDisplay bude atribut ignorován.

Poznámka:

Pro nativní kód je tento atribut podporován pouze v kódu C++/CLI.

Následující tabulka uvádí některé možné použití atributu DebuggerDisplay a ukázkových výstupů.

Atribut Výstup zobrazený ve sloupci Hodnota
[DebuggerDisplay("x = {x} y = {y}")]

Používá se u typu s poli x a y.
x = 5 y = 18
[DebuggerDisplay("String value is {getString()}")]Syntaxe parametrů se může mezi jazyky lišit. Proto ho používejte opatrně. String value is [5, 6, 6]

DebuggerDisplay může také přijímat pojmenované parametry.

Parametry Účel
Name, Type Tyto parametry ovlivňují sloupce Name a Type v oknech proměnných. (Mohou být nastaveny na řetězce pomocí stejné syntaxe jako konstruktor.) Nadměrné využití těchto parametrů nebo jejich nesprávné použití může způsobit matoucí výstup.
Target, TargetTypeName Určuje cílový typ při použití atributu na úrovni sestavení.

Soubor autoexp.cs používá atribut DebuggerDisplay na úrovni sestavení. Soubor autoexp.cs určuje výchozí rozšíření, která sada Visual Studio používá pro objekty .NET. V souboru autoexp.cs můžete prozkoumat příklady použití atributu DebuggerDisplay nebo můžete upravit a zkompilovat soubor autoexp.cs a změnit výchozí rozšíření. Než soubor autoexp.cs upravíte, nezapomeňte ho zálohovat.

Pokud chcete sestavit soubor autoexp.cs, otevřete příkazový řádek pro vývojáře pro VS2015 a spusťte následující příkazy.

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

Změny souboru autoexp.dll se vyberou v další relaci ladění.

Použití výrazů v DebuggerDisplay

I když můžete použít obecný výraz mezi složenými závorkami v atributu DebuggerDisplay, tento postup se nedoporučuje.

Obecný výraz v DebuggerDisplay má implicitní přístup k this ukazateli pouze pro aktuální instanci cílového typu. Výraz nemá přístup k aliasům, místním prostředím ani ukazatelům. Pokud výraz odkazuje na vlastnosti, atributy těchto vlastností se nezpracují. Například kód [DebuggerDisplay("Object {count - 2}")] jazyka C# by se zobrazil Object 6 , pokud by pole count bylo 8.

Použití výrazů v DebuggerDisplay může vést k následujícím problémům:

  • Vyhodnocení výrazů je nejlevnější operací v ladicím programu a výraz se vyhodnocuje při každém zobrazení. To může způsobit problémy s výkonem při procházení kódu. Například složitý výraz, který se používá k zobrazení hodnot v kolekci nebo seznamu, může být velmi pomalý, pokud je počet prvků velký.

  • Výrazy se vyhodnocují vyhodnocovačem výrazů jazyka aktuálního rámce zásobníku, nikoli vyhodnocovačem jazyka, ve kterém byl výraz napsán. To může způsobit nepředvídatelné výsledky, pokud se jazyky liší.

  • Vyhodnocení výrazu může změnit stav aplikace. Například výraz, který nastaví hodnotu vlastnosti ztlumí hodnotu vlastnosti v prováděcím kódu.

    Jedním ze způsobů, jak snížit možné problémy vyhodnocení výrazu, je vytvoření privátní vlastnosti, která provádí operaci a vrací řetězec. Atribut DebuggerDisplay pak může zobrazit hodnotu této privátní vlastnosti. Následující příklad implementuje tento vzor:

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

Přípona ",nq" říká vyhodnocovači výrazů, aby při zobrazení konečné hodnoty odebral uvozovky (nq = žádné uvozovky).

Příklad

Následující příklad kódu ukazuje, jak používat DebuggerDisplay, spolu s DebuggerBrowsable a DebuggerTypeProxy. Při zobrazení v okně proměnných ladicího programu, jako je okno Kukátko , vytvoří rozšíření, které vypadá takto:

Název Hodnota Typ
Key "tři" object {string}
Hodnota 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;
            }
        }
    }
}