Da jeg var ung, kunne man i Visual C++ 6.0 selv definere, hvordan typer skulle vises i watch-vinduet ved at rette i en hemmelig tekstfil i notepad.  Det er også muligt i VS.NET, men det kræver kode i stedet for konfiguration.  Man kan nemlig gøre det vha. DebuggerDisplayAttribute.  I modsætning til VC++ løsningen kan man derfor kun ændre visningen for sine egne typer.

Jeg vil her vise, hvordan DebuggerDisplayAttribute bruges.  Vi tager udgangspunkt i følgende type:

class MyClass
{
    public int Number { get; set; }
    public string Text { get; set; }
}

Følgende skærmbillede af watch-vinduet viser standardvisningen for vores type:

default

Hvis man ønsker at vise noget andet end den ikke specielt sigende tekst "{ConsoleApplication3.MyClass}", er den nemme løsning at override ToString:

public override string ToString()
{
    return String.Format("Number={0}, Text=\"{1}\"", Number, Text);
}

Overrides af ToString vil altid blive kaldt af debuggeren i watch-vinduet.  Med den metode kan man få vist, hvad man vil - f.eks.:

tostring

Hvis man ikke ønsker at override ToString bare for at vise noget pænt ved debugging, er DebuggerDisplayAttribute vejen at gå.  Koden kommer til at se således ud:

[DebuggerDisplay("Number={Number}, Text={Text}")]
class MyClass
{
    public int Number { get; set; }
    public string Text { get; set; }
}

 

Resultatet er det samme som ved brug af ToString.  DebuggerDisplay vil altid blive brugt i stedet for ToString af debuggeren.  Bemærk at debuggeren selv indsætter anførselstegn omkring strenge ved brug af DebuggerDisplay.

Som standard viser watch-vinduet alle properties og fields (public såvel som private), når man klikker på '+' ved siden af variabelnavnet.  Vha. en anden attribute, DebuggerBrowsable, kan man helt fjerne properties fra visningen:

[DebuggerDisplay("Number={Number}, Text={Text}")]
class MyClass
{
    public int Number { get; set; }
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public string Text { get; set; }
}

Det giver følgende visning:

DebuggerBrowsable

Man har også mulighed for helt at ændre denne visning vha. en tredje attribute, DebuggerTypeProxy:

[DebuggerDisplay("Number={Number}, Text={Text}")]
[DebuggerTypeProxy(typeof(MyClassDebugView))]
class MyClass
{
    public int Number { get; set; }
    public string Text { get; set; }

    internal class MyClassDebugView
    {
        MyClass c;

        public MyClassDebugView(MyClass c)
        {
            this.c = c;
        }

        public string NumberAndText { get { return c.Number.ToString() + ", " + c.Text; } }
    }
}

 

Debuggeren kalder constructoren for MyClassDebugView med det objekt af typen MyClass, som bliver vist i watch.  Nedenfor er vist, hvordan det kommer til at se ud i watch-vinduet.  Bemærk at debuggeren selv tilføjer et raw-view.

DebuggerTypeProxy