Search code examples
c#visual-studio-debuggingdebuggerdisplay

How to make DebuggerDisplay work for composite types in Dictionary?


In an attempt to pleasantly display a Dictionary's content, I wrote this:

[assembly: DebuggerDisplay("{Key,nq} -> {Value,nq}", Target = typeof(KeyValuePair<,>))]

namespace test {
    [DebuggerDisplay("{DebuggerDisplay,nq}")]
    public class Thing {
        private readonly int _num;
        public string DebuggerDisplay => $"DBG: {_num}";
        public Thing(int num) => _num = num;
    }

    public class Program {
        static void Main(string[] args) {
            var map = new Dictionary<string,Thing> {
                ["Foo"] = new Thing(1),
                ["Bar"] = new Thing(2),
            };
        }
    }
}

And I would've expected to see in the debugger this:

Foo -> DBG: 1
Bar -> DBG: 2

But instead I see this:

Foo -> {test.Thing}
Bar -> {test.Thing}

It's worth noting that if I expand on of the KeyValuePairs, I do see that:

Name    | Value
--------+-------
Key     | "Foo"
Value   | DBG: 1

So the DebuggerDisplay does work.

So the problem is how to display the content of a composite type in the main watch-list of the dictionary's content?


Solution

  • Though nested evaluation of DebuggerDisplay does not work it is actually flexible enough to call any custom formatting method with parameters. So I would do it like this:

    [assembly:DebuggerDisplay("{Key,nq} -> {MyNamespace.DebugHelper.DisplayValue(this.Value),nq}", Target = typeof(KeyValuePair<,>))]
    

    Where debug helper can be an internal helper class:

    internal static class DebugHelper
    {
        internal static string DisplayValue(object value)
        {
            switch (value)
            {
                case Thing thing:
                    return thing.DebuggerDisplay; // or even better just to format it here
                default:
                    return value.ToString();
            }
        }
    }