Built from source at 293d77f (0.1.17), net10.0, Windows x64, compared against netcoredbg 3.2.0-1092.
SharpDbg is the only one of the two that honours [DebuggerDisplay] at all, so all of this is ahead of netcoredbg, which renders {Ns.Type} for every annotated type. Six things in the rendering look wrong. Separate fixes, but one attribute, so one issue.
Types, one local of each:
[DebuggerDisplay("{Amount} {Currency,nq}")]
sealed class Money { public decimal Amount; public string Currency; } // 12.5m, "USD"
[DebuggerDisplay("{Amount} {Currency}")]
sealed class QuotedMoney { public decimal Amount; public string Currency; } // same values
[DebuggerDisplay("\\{{Value}\\}")]
sealed class Braced { public int Value = 3; }
[DebuggerDisplay("{NoSuchMember}")]
sealed class Missing { public int Value = 2; }
[DebuggerDisplay("{_name,nq} -> {Next._name,nq}")]
sealed class Link { string _name; public Link? Next; } // "head" -> "tail", tail.Next is null
[DebuggerDisplay("{Value}", Name = "renamed", Type = "RetypedThing")]
sealed class Labelled { public int Value = 11; }
[DebuggerDisplay("base {Tag,nq}")]
class Base { public string Tag = "b"; }
sealed class Derived : Base { public int Extra = 9; } // declares no display of its own
| local |
SharpDbg |
expected |
money |
12.5 USD |
12.5 USD |
quoted |
12.5 USD |
12.5 "USD" |
braced |
error: A '{' character may only be escaped by doubling |
{3} |
missing |
error: The name 'NoSuchMember' does not exist... |
value keeps the parts that resolved |
link head |
head -> tail |
head -> tail |
link tail |
error: CIL execution failed ... NullReferenceException |
tail -> <error> in that fragment only |
labelled |
renamed = 11 |
value 11, name column renamed, type column RetypedThing |
derived |
{Display.Derived} |
base b |
-
A string fragment is never quoted. money and quoted render identically, so ,nq is a no-op and a quoted string cannot be asked for. ,nq means "no quotes", which implies quotes are the default.
-
\{ and \} are not implemented. These are the documented escape for a literal brace. It looks like the display string is compiled as a C# interpolated string, so the backslash fails the whole value. {{ and }} are the interpolated-string escape, not the DebuggerDisplay one.
-
A fragment that cannot be resolved replaces the whole value. Name={Name} Bad={Nope} loses the half that worked. The error belongs in that fragment's place.
-
A null anywhere on a fragment's member path throws out of the IL interpreter. tail has Next == null, and the whole display becomes a NullReferenceException text. The head of the same list renders fine. A linked structure whose last node has a null link is ordinary, and the same fix as 3 covers it: put the error in the fragment, keep the rest.
-
Name = is folded into the value and Type = is dropped. labelled renders as renamed = 11. Both name columns rather than the value: Name names the variable, Type the type column, and neither belongs in the value text.
-
Attribute inheritance is not honoured, though DebuggerDisplayAttribute is Inherited = true. Derived declares no display and should get base b from Base. This one is only visible if you compare implementations, since a debugger that has no DebuggerDisplay at all produces the same output for it.
Happy to test a branch against these if useful, I have all eight shapes as locals in one program.
Built from source at
293d77f(0.1.17), net10.0, Windows x64, compared against netcoredbg 3.2.0-1092.SharpDbg is the only one of the two that honours
[DebuggerDisplay]at all, so all of this is ahead of netcoredbg, which renders{Ns.Type}for every annotated type. Six things in the rendering look wrong. Separate fixes, but one attribute, so one issue.Types, one local of each:
money12.5 USD12.5 USDquoted12.5 USD12.5 "USD"bracederror: A '{' character may only be escaped by doubling{3}missingerror: The name 'NoSuchMember' does not exist...linkheadhead -> tailhead -> taillinktailerror: CIL execution failed ... NullReferenceExceptiontail -> <error>in that fragment onlylabelledrenamed = 1111, name columnrenamed, type columnRetypedThingderived{Display.Derived}base bA string fragment is never quoted.
moneyandquotedrender identically, so,nqis a no-op and a quoted string cannot be asked for.,nqmeans "no quotes", which implies quotes are the default.\{and\}are not implemented. These are the documented escape for a literal brace. It looks like the display string is compiled as a C# interpolated string, so the backslash fails the whole value.{{and}}are the interpolated-string escape, not the DebuggerDisplay one.A fragment that cannot be resolved replaces the whole value.
Name={Name} Bad={Nope}loses the half that worked. The error belongs in that fragment's place.A null anywhere on a fragment's member path throws out of the IL interpreter.
tailhasNext == null, and the whole display becomes aNullReferenceExceptiontext. The head of the same list renders fine. A linked structure whose last node has a null link is ordinary, and the same fix as 3 covers it: put the error in the fragment, keep the rest.Name =is folded into the value andType =is dropped.labelledrenders asrenamed = 11. Both name columns rather than the value:Namenames the variable,Typethe type column, and neither belongs in the value text.Attribute inheritance is not honoured, though
DebuggerDisplayAttributeisInherited = true.Deriveddeclares no display and should getbase bfromBase. This one is only visible if you compare implementations, since a debugger that has noDebuggerDisplayat all produces the same output for it.Happy to test a branch against these if useful, I have all eight shapes as locals in one program.