In Visual Studio, is it possible to customize the order in which properties are displayed when inspected in the debugger?
Here's an example of a class where I'd really like StartDate and EndDate to appear next to each other, even though they are separated alphabetically .
Other debugger options are customizable through attributes like the DebuggerDisplayAttribute
, so I was hopeful that another such attribute would exist for DisplayOrder.
[DebuggerDisplay("{Name}")]
public class Rule
{
public string Name;
public int MaxAge;
public DateTime StartDate;
public DateTime EndDate;
}
In an ideal world, I'd like the ability to order the properties in the inspector in the order that I have defined on the class (even if that requires setting an debugger order attribute incrementally on each property) so the display would look like this:
Pinnable Properties in VS2019+ are a way to go currently, since you can pin your properties in correct order using the button inside the datatip.
However, in a more general, reusable approach, the [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
attribute can be used on an array of ordered property name and value pairs. This enables the debug view to 'flatten' the array root, listing the properties in correct order.
Further expanding on KyleMit's answer, and using reflection to load the list of members and fields, makes such a debug view reusable:
[DebuggerDisplay("{Name}")]
[DebuggerTypeProxy(typeof(OrderedPropertiesView))]
public class Rule
{
public string Name;
public int MaxAge;
public DateTime StartDate;
public DateTime EndDate;
}
public class OrderedPropertiesView
{
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public SimpleProperty[] Properties { get; }
public OrderedPropertiesView(object input)
{
this.Properties = input.GetType()
.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Select(prop => new SimpleProperty(prop, input))
.ToArray();
}
[DebuggerDisplay("{Value}", Name = "{PropertyName,nq}")]
public class SimpleProperty
{
public SimpleProperty(MemberInfo member, object input)
{
this.Value = GetValue(member, input);
this.PropertyName = member.Name;
}
private object GetValue(MemberInfo member, object input)
{
switch (member)
{
case FieldInfo fi: return fi.GetValue(input);
case PropertyInfo pi: return pi.GetValue(input);
default: return null;
}
}
public object Value { get; internal set; }
public string PropertyName { get; internal set; }
}
}
Which looks like this in the debugger:
The order of properties and fields might not be guaranteed with reflection, but since the view is only for debugging purposes, it should be enough. If not, Properties
array can be constructed manually, limiting the reusability. In either case, Properties
are not really properties, therefore expanding the SimpleProperty
datatip looks like this:
Notice that the property inspector can only be used in the expanded SimpleProperty.Value
, which might be an inconvenience.
Just to run out the ball on JCL's suggestion to use #if DEBUG
with a caluclated property. If you wanted some extra information in the debugger, you could add a field only when in debug mode like this:
[DebuggerDisplay("{Name}")]
public class Rule
{
public string Name;
public int MaxAge;
public DateTime StartDate;
public DateTime EndDate;
#if DEBUG
private string DateRange
{
get { return StartDate.ToString("dd/MM/yyyy") + " - "+
EndDate.ToString("dd/MM/yyyy");
}
}
#endif
}
Which would look like this:
This gets information presented together, but will still add noise to the inspector.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With