Enhance your debugging experience by customizing debugger output

September 20, 2017

Chances are if you’ve debugged something in Visual Studio you’ve set a watch on an object and seen something like this in the Watch window output:

Some Alt Text

The value {DebuggerSample.Employee} isn’t particularly useful. If you want more data about that Employee object you have to drill down into it’s fields and properties to see what’s going on. This can be a pain. Sometimes it’s useful to have customized output displayed instead of just the type name. For example, instead of {DebuggerSample.Employee} I want to see Name: FirstName LastName in the debugger output. There are a couple ways to do this. To demonstrate them I’ll use this Employee class:

using System;
using System.Diagnostics;
namespace DebuggerSample
{
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsFullTime { get; set; }
public Employee(string firstName, string lastName, bool isFullTime = false)
{
FirstName = firstName;
LastName = lastName;
IsFullTime = isFullTime;
}
}
}
view raw Employee.cs hosted with ❤ by GitHub

Override ToString()

The first way to do it is to override ToString() on Employee:

using System;
using System.Diagnostics;
namespace DebuggerSample
{
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsFullTime { get; set; }
public Employee(string firstName, string lastName, bool isFullTime = false)
{
FirstName = firstName;
LastName = lastName;
IsFullTime = isFullTime;
}
public override string ToString()
{
return $"Name: {FirstName} {LastName}";
}
}
}
view raw Employee-ToString.cs hosted with ❤ by GitHub

That will give you the desired result in the debug window. It’s simple and concise and works well in most cases. But what if for some reason ToString() is used elsewhere in the application and needs it in a different output format?

DebuggerDisplay

The second method is the System.Diagnostics.DebuggerDisplayAttribute. All I have to do here is annotate the class with that attribute and give it an expression to evaluate. In this example the expression is Name: {FirstName,nq} {LastName,nq}. It replaces {FirstName} and {LastName} with the values of those properties. The ,nq qualifier just tells the debugger not to wrap the values in quotes, which is the default behavior.

using System;
using System.Diagnostics;
namespace DebuggerSample
{
[DebuggerDisplay("Name: {FirstName,nq} {LastName,nq}")]
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsFullTime { get; set; }
public Employee(string firstName, string lastName, bool isFullTime = false)
{
FirstName = firstName;
LastName = lastName;
IsFullTime = isFullTime;
}
}
}

As you can see the output is the same. The DebuggerDisplay method has an added benefit in that it can also be used on properties and fields to customize the debugger output.

Compatibility (and a warning!)

Both ToString() and DebuggerDisplay also work in Visual Studio Code’s debugger as well (since System.Diagnostics is part of .NET Standard).

If you are going to customize the output you should keep in mind that if ToString() or the DebuggerDisplay expression takes too long to execute you are going to get a major debugging performance hit. Also be sure not to include any methods or properties that mutate the state of the object when it’s executed. That will cause all kinds of confusion when you’re debugging.


© 2020 Jesse Barocio. Built with Gatsby