问题
I've got a class which inherits from a List<MagicBean>
. It works well and as expected in all respects except one: when I add the [DebuggerDisplay]
attribute. Even though looking at List has its as [DebuggerDisplay("Count = {Count}")]
, if I so much as copy and paste that onto mine, I lose the ability to look directly at all of the MagicBeans I have without drilling into base->private members while debugging.
How do I get the best of both worlds? IE: Custom value in the value column, and Visual Studio not hiding my magic beans from me?
回答1:
You can get the effect you need by using the DebuggerTypeProxy attribute. You need to create a class to make a debug "visualisation" of your inherited list:
internal sealed class MagicBeanListDebugView
{
private List<MagicBean> list;
public MagicBeanListDebugView(List<MagicBean> list)
{
this.list = list;
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public MagicBean[] Items{get {return list.ToArray();}}
}
You can then declare this class to be used by the debugger for displaying your class, along with the DebuggerDisplay
attribute:
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(MagicBeanListDebugView))]
public class MagicBeanList : List<MagicBean>
{}
This will give you the "Count = 3" message when you hover over an instance of your inherited list in Visual Studio, and a view of the items in the list when you expand the root node, without having to drill down into the base properties.
Using ToString()
to specifically get debug output is not a good approach, unless of course you are already overriding ToString()
for use in your code elsewhere, in which case you can make use of it.
回答2:
After looking at the "Using DebuggerDisplay Attribute" article on MSDN, they suggest that you could override the ToString() function of your class as an alternate option rather than using DebuggerDisplay attribute. Overriding the ToString() method won't hide your beans either.
If a C# object has an overridden ToString(), the debugger will call the override and show its result instead of the standard {}. Thus, if you have overridden ToString(), you do not have to use DebuggerDisplay. If you use both, the DebuggerDisplay attribute takes precedence over the ToString() override.
Are you able to override the ToString() method on your class or are you using it for other purposes?
I don't know if you've already considered this or not, but I thought I'd suggest it just incase it helps. :-)
For completeness so anyone else can quickly mock it up; here's a quick example that I made:
namespace StackOverflow
{
//broken BeanPouch class that uses the DebuggerDisplay attribute
[System.Diagnostics.DebuggerDisplay("Count = {Count}")]
class BrokenBeanPouch : List<MagicBean>
{ }
//working BeanPouch class that overrides ToString
class WorkingBeanPouch : List<MagicBean>
{
public override string ToString()
{
return string.Format("Count = {0}", this.Count);
}
}
class Program
{
static WorkingBeanPouch myWorkingBeans = new WorkingBeanPouch()
{
new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m }
};
static BrokenBeanPouch myBrokenBeans = new BrokenBeanPouch()
{
new MagicBean() { Value = 4.99m }, new MagicBean() { Value = 5.99m }, new MagicBean() { Value = 3.99m }
};
static void Main(string[] args)
{
//break here so we can watch the beans in the watch window
System.Diagnostics.Debugger.Break();
}
}
class MagicBean
{
public decimal Value { get; set; }
}
}
回答3:
Use the DebuggerDisplay attribute like so:
[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]`
class Project
{
int ID{get;set;}
IList<Customer> Customers{get;set;}
}
Some more info here.
来源:https://stackoverflow.com/questions/1100506/how-to-make-debuggerdisplay-respect-inherited-classes-or-at-least-work-with-co