Sdílet prostřednictvím


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

DebuggerDisplayAttribute řídí, jak se objekt, vlastnost nebo pole zobrazují v oknech proměnných ladicího programu. Tento atribut lze použít pro typy (třídy, struktury, výčty, delegáty), ale obvykle se používá pouze pro třídy a struktury. 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 hodnot pro instance typu. Tento řetězec může obsahovat složené závorky ({ a }). Text v rámci dvojice křivých závorek se vyhodnotí jako pole, vlastnost nebo metoda.

Pokud má třída přepsanou metodu ToString(), ladicí program používá tuto přepsanou metodu místo výchozí metody {<typeName>}. V takovém případě nemusíte používat DebuggerDisplay. Pokud použijete obojí, má atribut DebuggerDisplay přednost před přepsánou metodou ToString(). Atribut DebuggerDisplay má také přednost před přepsánou metodou ToString() v podtřídě.

Zda ladicí program vyhodnotí toto implicitní ToString() volání, závisí na možnosti ladění v části Nástroje (nebo Ladění) >Možnosti.

Important

Pokud vyberete možnost Zobrazit nezpracovanou strukturu objektů v oknech proměnných , DebuggerDisplay atribut se ignoruje. Toto nastavení se nachází v podokně Nástroje>Možnosti v části Všechna nastavení>Ladění>Obecné.

Important

Pokud vyberete možnost Zobrazit nezpracovanou strukturu objektů v oknech proměnných , DebuggerDisplay atribut se ignoruje. Toto nastavení se nachází v dialogovém okně Nástroje>Možnosti v části Ladění>Obecné.

Note

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ů.

Attribute 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 parametru se může mezi jazyky lišit. Proto ho používejte opatrně. String value is [5, 6, 6]

DebuggerDisplay mohou také přijímat pojmenované parametry.

Parameters Purpose
Name, Type Tyto parametry ovlivňují Název a Typ sloupců oken 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í. Před úpravou nezapomeňte zálohovat soubor autoexp.cs .

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

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

Změny 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 ukazateli this pouze pro aktuální instanci cílového typu. Výraz nemá přístup k aliasům, lokálním proměnným ani ukazatelům. Pokud výraz odkazuje na vlastnosti, atributy těchto vlastností se nezpracují. Například C# kód [DebuggerDisplay("Object {count - 2}")] se zobrazí jako Object 6, pokud pole count má hodnotu 8.

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

  • Vyhodnocení výrazů je nejnákladnější operací v ladicím programu a výraz se vyhodnotí 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, změní 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). Další informace o formátovacích nástrojích naleznete v tématu Specifikátory formátu v jazyce C#.

Example

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

Name Value Type
Key "three" object {string}
Value 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;
            }
        }
    }
}