.NET Debugging Tricks: Formatting Class Appearance in the VS Watch Window

These are two cool tricks that I just learned from a friend and colleague - Mike.

Formatting How Your Class Appears in the Locals/Watch Window

                You can format how your class appears in the locals window or the watch window by setting the [DebuggerDisplay] attribute. For example, I’ve set the following two attributes on two new structs I’ve been working with:

    [DebuggerDisplay("R={Red} G={Green} B={Blue}")]

    internal struct RgbColor {

        public float Red;

        public float Green;

        public float Blue;

    }

    [DebuggerDisplay("H={Hue} L={Lightness} S={Saturation}")]

    internal struct HlsColor {

        public float Hue;

        public float Lightness;

        public float Saturation;

    }

                And as a result I get the following nicely formatted output in the Locals window or when I hover over the variable in the source file:

         Watches window shows formatted classes

You can even set this attribute on classes from other assemblies that you don’t have source code for, but it’s a bit more involved.

Inspecting Managed Object without Reference on the Current Thread

The Make Object ID command in Visual Studio allows you to assign an ID to a managed object, and inspect it in the debugger even if you don’t have a reference to it on the current thread. This is very handy when you have an object that’s being modified by someone else’s code and you want to figure out when it’s getting changed. It can also help you determine if you’re looking at the same instance of an object at different breakpoints; this can be handy for things like collections. It’s a lot easier than dumping the hash code every time

 

· To assign an object ID, right-click on your object in the locals window and select Make Object ID. It will append a number to the value field, such as:

 

{MyNamespace.MyClass} {1#}

 

You can now type 1# in a watch window at any time and inspect your object, and you can use #1 in the immediate window. For example, if you’re tracking down a memory leak you can break and type

 

GC.GetGeneration(1#)

 

And determine what generation your object is in.

watch1.jpg