如何使[DebuggerDisplay]尊重继承类或至少与集合一起使用?

14

我有一个继承自 List<MagicBean> 的类。它在所有方面都表现良好,并如预期一样,唯一的问题是添加了 [DebuggerDisplay] 属性后出现了异常。即使我将其复制并粘贴到我的类中,仅这样就会导致在调试时不能直接查看所有 MagicBeans,而需要钻入基类和私有成员。

该如何既实现自定义值列,又不影响 Visual Studio 在调试时显示我的 Magic Beans?

3个回答

12

通过使用DebuggerTypeProxy属性,您可以获得所需的效果。 您需要创建一个类来对继承列表进行调试“可视化”:

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();}}
}

你可以使用DebuggerDisplay属性来声明这个类被调试器用于显示,例如:

[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(MagicBeanListDebugView))]
public class MagicBeanList : List<MagicBean>
{}

当您在Visual Studio中悬停在继承列表的实例上时,此代码将显示“Count = 3”消息,并且在展开根节点时可以查看列表中的项,而无需深入基本属性。

使用ToString()来特别获取调试输出并不是一个好方法,除非您已经在其他地方覆盖了ToString()以供您的代码使用,在这种情况下,您可以利用它。


Nifty很有用,但看起来相当复制黏贴。我现在无法进行测试,但是否有某种方法可以使用List已经使用的代码,或者至少能够编写一次通用版本?我不想为每个自定义容器类输入这个东西。 - MighMoS
经过一番搜索,显然答案是否定的。 - MighMoS

2
在MSDN上查看“使用DebuggerDisplay属性”文章后,他们建议您可以重写类的ToString()函数作为替代选项,而不是使用DebuggerDisplay属性。 重写ToString()方法也不会隐藏您的信息。
引用:“如果C#对象已覆盖ToString(),调试器将调用该覆盖并显示其结果,而不是标准{}。因此,如果您已经覆盖了ToString(),则不必使用DebuggerDisplay。如果同时使用两者,则DebuggerDisplay属性优先于ToString()覆盖。”
您能否在类上重写ToString()方法或者您正在将其用于其他目的?
我不知道您是否已经考虑过这一点,但我想提出建议,以防有帮助。:-)
为了完整起见,让任何人都可以快速模拟它;这是我制作的一个快速示例:
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; }
    }    
}

-1
使用DebuggerDisplay属性的方法如下:
[DebuggerDisplay("ID:{ID},Customers:{Customers==null?(int?)null:Customers.Count}")]`
class Project
{
    int ID{get;set;}
    IList<Customer> Customers{get;set;}
}

这个回答在“低质量回答队列”中。 - moken
1
供参考:这个回答没有透露下面的URL是作者的。请参阅如何避免成为垃圾邮件发送者 - LW001

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接