【问题标题】:Is it possible to use conditions in a DebuggerDisplay?是否可以在 DebuggerDisplay 中使用条件?
【发布时间】:2012-10-05 06:16:55
【问题描述】:

考虑以下类:

[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}。我将如何实现这一目标?

【问题讨论】:

  • 简单地添加一个返回你想要的方法怎么样?我个人通常会覆盖ToString,但您可以简单地添加一些其他方法,并将其用作调试器字符串。
  • 可以做到,但那将是最后的手段,因为方法向类引入了仅用于调试的功能。像这样的东西闻起来像一个糟糕的设计。出于调试目的,我从不覆盖 ToString()

标签: c# .net debugging debuggerdisplay


【解决方案1】:

您可以使用conditional operator (?:)

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

IsTempFile == false


IsTempFile == true

【讨论】:

  • 哇!你值得喝啤酒! (刚刚删除了逗号前的空格。)你有这方面的文档吗?
  • @KeesC.Bakker 这只是 ? operator 被用作表达式的一部分
  • 我不知道我们可以在这些“魔法”字符串中做这样的事情。
【解决方案2】:

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

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

要考虑的另一件主要事情是表达式由使用类的语言的调试器评估。 如果该类及其所有潜在用户都在 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;
    }
  }

}

这是一个私有属性,所以它不会妨碍任何潜在的子类。

【讨论】:

    【解决方案3】:

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

    第二,这里有一篇文章:

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

    【讨论】:

    • 请注意,当使用的代码是 Visual Basic(或 null == MyKids ? 0 : MyKids.Count 不是有效表达式的其他语言)时,您的第三个示例将中断。您链接的文章甚至特别提到了这一点。
    • @Zastai 感谢您提供有关可能存在的陷阱的说明。
    【解决方案4】:

    您可以将它与 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());
            }
        }
    }
    

    Watch

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-26
      • 2012-08-08
      • 1970-01-01
      • 1970-01-01
      • 2014-06-09
      • 2021-11-06
      • 2015-10-28
      • 1970-01-01
      相关资源
      最近更新 更多