【笔记】DebuggerDisplay、DebuggerBrowsable 及其相关“系列”特性的系统性说明

下面是对 DebuggerDisplay、DebuggerBrowsable 及其相关"系列"特性的系统性说明,涵盖概念、语法、选项、示例、性能与调试器行为等。

一、DebuggerDisplay

  • 作用:自定义对象在调试器中的显示文本(Locals/Watch/数据提示)。
  • 用法:在类型或成员上标注 [DebuggerDisplay("格式字符串")]
  • 格式字符串语法:
    • 文本常量:"MyType"
    • 引用成员:{Member},支持属性、字段、无参实例方法,如 {Id}{Count}{GetState()}
    • 去引号:{Name,nq} 对字符串去除引号
    • 可组合:"Id={Id}, Count={Items.Count}, Ready={IsReady}"
  • 注意事项:
    • 求值发生在调试暂停时,若成员访问抛异常,调试器显示错误提示。
    • 避免昂贵或有副作用的 getter/方法。
  • 示例(通用):
csharp 复制代码
using System.Diagnostics;

[DebuggerDisplay("{Name,nq} (Id={Id}, Count={Items.Count})")]
public class Sample
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<int> Items { get; } = new List<int>();
  }

二、DebuggerBrowsable

  • 作用:控制成员在调试器中的可见性与展开方式,减少噪声或提供更友好的展开视图。
  • 用法:标注在字段或属性上(常用于字段)。
  • 枚举值:
    • DebuggerBrowsableState.Never:在调试器中隐藏该成员。
    • DebuggerBrowsableState.RootHidden:将该成员的元素直接作为父对象的子级展开显示(典型用于集合字段/属性)。
    • DebuggerBrowsableState.Collapsed:成员在调试器中默认折叠(具体效果依调试器版本而定,常见实现可能忽略)。
  • 示例(隐藏或扁平化集合):
csharp 复制代码
using System.Diagnostics;

public class Bag<T>
{
    [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
    public T[] Items;

    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private string _debugNoise; // 在调试器中不显示
  }
  • 注意事项:
    • RootHidden 适用于返回数组或实现 IEnumerable 的成员;展开时元素直接显示,父级容器成员名不出现。
    • 对属性使用时需留意 getter 是否有副作用。

三、DebuggerTypeProxy(同属"调试视图系列",常与以上配合)

  • 作用:为类型提供一个"调试专用代理视图",在调试器中以代理的公开成员来展示对象,适合复杂对象/集合。
  • 用法:在类型上标注 [DebuggerTypeProxy(typeof(MyTypeDebugView))]
  • 示例(为集合自定义可读视图):
csharp 复制代码
using System.Diagnostics;
using System.Linq;

[DebuggerTypeProxy(typeof(InventoryDebugView))]
public class Inventory
{
    public List<Item> Items { get; } = new List<Item>();
    public string Name { get; set; }
}

internal sealed class InventoryDebugView
{
    private readonly Inventory _inv;
    public InventoryDebugView(Inventory inv) => _inv = inv;

    // 在调试器中以数组展开
    public object[] Items => _inv.Items
        .Select(i => new { i.Id, i.Title, i.Stock })
          .ToArray();
  }
  • 注意事项:
    • 代理仅在调试器中使用,不参与运行。
    • 代理成员应轻量、无副作用,避免 IO/锁/昂贵计算。

四、DebuggerStepThrough / DebuggerNonUserCode / DebuggerHidden(相关调试行为特性)

  • DebuggerStepThrough:指示调试器在单步执行时跳过标注的代码(仍可设置断点)。
  • DebuggerNonUserCode:将代码标记为非用户代码,调试器默认不步入。
  • DebuggerHidden:隐藏方法,使调试器无法在此处设置断点或步入(慎用)。
  • 用途:控制单步体验,减少进入框架/样板代码。

五、组合最佳实践

  • DebuggerDisplay:展示关键、廉价、稳定的状态(Id、Name、Count、简单 Flags)。
  • DebuggerBrowsable:
    • 对"内部实现细节"使用 Never 隐藏,降低视觉噪声。
    • 对集合用 RootHidden 扁平化,便于直接查看元素。
  • DebuggerTypeProxy:为复杂对象/集合提供结构化视图(数组、投影),避免在 DebuggerDisplay 中塞过多信息。
  • 性能与安全:
    • 避免在调试视图中触发昂贵或有副作用操作(数据库、磁盘、网络、锁)。
    • Getter 内避免复杂副作用逻辑,防止调试卡顿。
    • 若遇到评估过于频繁导致性能问题,可调整 Visual Studio 设置:Tools > Options > Debugging > General,如关闭"Enable property evaluation and other implicit function calls"。

六、常见问题与规避

  • 成员名拼写错误导致显示为空或错误提示。
  • 在 DebuggerDisplay 中调用可能抛异常的方法,影响调试体验。
  • 使用 RootHidden 但返回类型不是可枚举/数组,导致视图不如预期。
  • 在代理视图或属性 getter 中执行昂贵逻辑引发卡顿或阻塞。

七、在 Visual Studio 中查看与验证

  • 暂停后在 Debug > Windows > LocalsWatch、悬停数据提示查看效果。
  • 如需精简自动求值,调整 Tools > Options > Debugging > General 的相关选项。
  • 若想只在调试器中显示某些成员,可以把它们放在代理视图中,原类型中使用 DebuggerBrowsable(Never) 隐藏实现字段。

了解更多

DebuggerDisplayAttribute Class

DebuggerBrowsableAttribute Class

DebuggerHiddenAttribute Class

DebuggerTypeProxyAttribute Class

System.Windows.Controls 命名空间 | Microsoft Learn

控件库 - WPF .NET Framework | Microsoft Learn

WPF 介绍 | Microsoft Learn

使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn

https://github.com/HeBianGu

HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频

GitHub - HeBianGu/WPF-Control: WPF轻量控件和皮肤库

GitHub - HeBianGu/WPF-ControlBase: Wpf封装的自定义控件资源库

相关推荐
其美杰布-富贵-李2 小时前
OpenCalphad 学习笔记
笔记·学习·热力学计算
hkNaruto2 小时前
【AI】AI学习笔记:直接使用Python+BM25算法实现RAG的可行性以及实用价值
人工智能·笔记·学习
Lv11770082 小时前
WinForm常用控件功能介绍及使用模板
笔记·c#·visual studio·winform
week_泽2 小时前
第7课:管理长期记忆的关键架构决策 - 学习笔记_7
java·笔记·学习·ai agent
koo3642 小时前
pytorch深度学习笔记15
pytorch·笔记·深度学习
ou.cs2 小时前
WPF TreeView 自动展开所有节点:附加行为(Attached Behavior)保姆级实现教程
c#·.net·wpf
鱼蛋-Felix3 小时前
C#浮点数在部分国家解析失效问题
开发语言·unity·c#
中屹指纹浏览器3 小时前
2026 指纹浏览器技术深度剖析:沙箱隔离与 IP 协同适配的实现方案
经验分享·笔记
被制作时长两年半的个人练习生3 小时前
首尾元素相同的间隔循环策略
c++·笔记·循环·ptx