是否可以在DebuggerDisplay中使用条件?

时间:2012-10-15 09:31:58

标签: c# .net debugging debuggerdisplay

考虑以下课程:

[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 个答案:

答案 0 :(得分:29)

您可以使用conditional operator (?:)

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

IsTempFile == false

enter image description here


IsTempFile == true

enter image description here

答案 1 :(得分:4)

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

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

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

  1. 无法保证调试器甚至根本不会使用[DebuggerDisplay]属性,
  2. 如果确实如此,则无法保证它会尝试评估{expression}块和
  3. 如果你开始做任何花哨的东西(比如使用?),它很有可能无法评估你的C#表达式。
  4. 最安全的做法是添加一个私有属性来计算调试器值:

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

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

答案 2 :(得分:0)

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

第二,这是一篇文章:

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

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

使用Visual Studio调试器自定义对象显示方式

莱斯利·理查森

程序管理器,Visual Studio调试和诊断

第三,这是一个基于空子集或不空子集的通用示例:

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

答案 3 :(得分:0)

您可以将其与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