27

考虑以下类:

[DebuggerDisplay("{GetType().Name,nq}: FileName = {FileName,nq}")]
public class FileWrapper
{
    public string FileName { get; set; }
    public bool IsTempFile { get; set; }
    public string TempFileName { get; set; }
}

我想添加一个基于IsTempFileName属性的调试器显示。, TempFileName = {TempFileName,nq}当实例是临时文件时,我想添加字符串。我将如何实现这一目标?

4

4 回答 4

34

您可以使用条件运算符 (?:)

[DebuggerDisplay("{GetType().Name,nq}: FileName = {FileName,nq}{IsTempFile ? \", TempFileName: \" + TempFileName : System.String.Empty,nq}")]

IsTempFile == false

在此处输入图像描述


IsTempFile == true

在此处输入图像描述

于 2012-10-15T09:50:43.950 回答
9

您可以使用任何有效的表达式。

但是,请记住,调试器会多次评估这些表达式,因此您使它们越复杂,您就越会开始注意到调试速度的降低(例如,在单步执行代码时)。

另一个需要考虑的主要事情是表达式由使用类的语言的调试器评估。如果该类及其所有潜在用户都在 C# 中,则没有问题,您可以使用三元运算符之类的东西。但是,如果您的课程也将使用另一种语言,那么:

  1. 不能保证调试器甚至会使用 [DebuggerDisplay] 属性,
  2. 如果是这样,则不能保证它会尝试评估 {expression} 块,并且
  3. 如果您开始做任何花哨的事情(例如使用?:),它很有可能无法评估您的 C# 表达式

最安全的做法是添加一个私有属性来计算调试器值:

[DebuggerDisplay("{DebugValue,nq}")]
public class FileWrapper {

  public string FileName     { get; set; }
  public bool   IsTempFile   { get; set; }
  public string TempFileName { get; set; }

  private string DebugValue {
    get {
      var text = string.Format("{0}: FileName={1}", this.GetType(), this.FileName);
      if (this.IsTempFile)
        text += string.Format(", TempFileName={0}", this.TempFileName);
      return text;
    }
  }

}

它是私有财产,因此不会妨碍任何潜在的子类。

于 2014-03-07T14:58:51.163 回答
1

您可以将它与 Extensions 方法一起使用。

using System;
using System.Linq;
using System.Diagnostics;
using System.ComponentModel;

namespace ConsoleApplicationDebuggerDisplay
{
    class Program
    {
        static void Main(string[] args)
        {
            MyObject o1 = new MyObject();
            MyObject o2 = new MyObject();
            o1.Items = new int[] { 1, 2, 3, 4 };
        }
    }

    [DebuggerDisplay("{DebuggerDisplay,nq}")]
    public class MyObject
    {
        [DebuggerDisplay("{Items.ToDebuggerDisplay(),nq}")]
        public int[] Items { get; set; }

        [DebuggerBrowsable(DebuggerBrowsableState.Never), Browsable(false)]
        internal string DebuggerDisplay
        {
            get
            {
                return string.Format("{{Items={0} ...}}"
                    , Items.ToDebuggerDisplay()
                    );
            }
        }
    }

    internal static class Extensions
    {
        public static bool IsNull(this object o)
        {
            return object.ReferenceEquals(o, null);
        }

        public static bool IsNotNull(this object o)
        {
            return !object.ReferenceEquals(o, null);
        }

        public static string ToDebuggerDisplay<T>(this System.Collections.Generic.IEnumerable<T> items)
        {
            if (items.IsNull())
                return "null";
            return string.Format("{{Count={0}}}", items.Count());
        }
    }
}

手表

于 2020-03-31T13:23:49.480 回答
1

首先,在我之前支持“懒惰”的答案......因为他们让我朝着正确的方向前进。

其次,这里有一篇文章:

https://devblogs.microsoft.com/visualstudio/customize-object-displays-in-the-visual-studio-debugger-your-way/

以下是文章的名称和作者,以防上面的链接将来失效。

以您的方式在 Visual Studio 调试器中自定义对象显示

莱斯利·理查森

程序经理,Visual Studio 调试和诊断

第三,这是一个基于 null 或非 null 子集合的更通用的示例:

[System.Diagnostics.DebuggerDisplay("ParentName = '{ParentName}', MyKidsCount='{null == MyKids ? 0 : MyKids.Count}'")]
public class MyParent
{
    public string ParentName { get; set; }

    public ICollection<MyKid> MyKids { get; set; }
}
于 2020-01-23T17:56:57.757 回答