使用“监视”窗口和“快速监视”监视变量

调试时,可以使用 Watch 窗口和 QuickWatch 来监视变量和表达式。 窗口仅在调试会话期间可用。

监视 窗口可以在调试时一次显示多个变量。 “ 快速监视 ”对话框一次显示一个变量,必须关闭,然后才能继续调试。 有关使用 QuickWatch 的详细信息,请参阅 使用 QuickWatch 观察单个变量或表达式

注释

如果你不熟悉调试代码,在阅读本文之前,你可能想要阅读 调试绝对初学者指南调试技术和工具

使用“监视”窗口观察变量

可以打开多个 监视 窗口,并在 监视 窗口中观察多个变量。

例如,要对以下代码中的abc 的值进行监视,请执行以下操作:

int main()
{
    int a, b, c;
    a = 1;
    b = 2;
    c = 0;

    for (int i = 0; i < 10; i++)
    {
        a++;
        b *= 2;
        c = a + b;
    }

    return 0;
}

  1. c = a + b;行上设置断点的方法是:单击左侧边距,选择调试>切换断点,或者按F9键。

  2. 选择绿色的“开始”箭头或“调试>开始调试”,或按 F5开始调试。 执行在断点处暂停。

  3. 通过选择“调试>>”或按 Ctrl>Alt++ 打开>”窗口。

    可以通过选择 Windows 234 来打开更多监视窗口。

  4. “监视 ”窗口中,选择一个空行,然后键入变量 a。 对bc执行相同的操作。

    监视变量的屏幕截图。

    监测变量的屏幕截图。

  5. 根据需要选择调试>单步进入或按F11继续调试。 当你遍历 for 循环时,监视 窗口中的变量值会更改。

注释

仅适用于C++,

  • 可能需要限定变量名称的上下文,或者使用变量名称的表达式。 上下文是变量所在的函数、源文件或模块。 如果必须限定上下文,请使用“监视”窗口中“名称”中的上下文运算符(C++)语法。

  • 可以使用 $<寄存器名称>@<寄存器名称> 将寄存器名称和变量名称添加到“监视”窗口中的名称。 有关详细信息,请参阅 伪变量

在监视窗口中使用表达式

可以在 监视 窗口中观察调试器识别的任何有效表达式。

例如,对于上一部分中的代码,可以通过在(a + b + c) / 3”窗口中输入来获取三个值的平均值:

监视表达式的屏幕截图。

监视表达式的屏幕截图。

“监视”窗口中计算表达式的规则通常与在代码语言中计算表达式的规则相同。 如果表达式出现语法错误,预期与代码编辑器中的编译器错误相同。 例如,上述表达式中的拼写错误在 监视 窗口中生成此错误:

监视表达式错误的屏幕截图。

监视表达式错误的屏幕截图。

带有两个波浪线图标的圆圈可能会在 “监视 ”窗口中显示。 此图标意味着调试器不会因为潜在的跨线程依赖项而计算表达式。 评估代码需要应用中的其他线程暂时运行,但由于处于中断模式,应用中的所有线程通常会停止。 允许其他线程暂时运行可能会对应用状态产生意外影响,调试器可能会忽略这些线程上的断点和异常等事件。

在“监视”窗口中搜索

可以使用每个窗口上方的搜索栏在 监视 窗口的名称、值和类型列中搜索关键字。 按 Enter 或选择其中一个箭头来执行搜索。 若要取消正在进行的搜索,请在搜索栏中选择“x”图标。

分别使用向左和向右箭头(Shift+F3 和 F3)在找到的匹配项之间导航。

监视窗口中搜索的屏幕截图。

若要使搜索更彻底或更深入,请使用“监视”窗口顶部的“搜索深度”下拉列表选择要搜索到嵌套对象中的级别数。

在“监视”窗口中固定属性

注释

.NET Core 3.0 或更高版本支持此功能。

可以使用“可固定属性”工具,在“监视”窗口通过对象的属性快速检查对象。 要使用此工具,请将鼠标悬停在某个属性上,并选择出现的固定图标,或右键单击并选择所显示上下文菜单中的“将成员固定到收藏夹”选项。 此操作将该属性置于对象属性列表的顶部,属性名称和值显示在“值”列中。 要取消固定属性,请再次选择固定图标,或在上下文菜单中选择“取消将成员固定到收藏夹”选项

“监视”窗口中固定属性的屏幕截图。

还可以在“监视”窗口中查看对象的属性列表时切换属性名称和筛选出非固定属性。 可以通过选择监视窗口上方工具栏中的按钮来访问这两个选项。

刷新监视值

计算表达式时,刷新图标(圆形箭头)可能会出现在 “监视 ”窗口中。 刷新图标指示错误或已过期的值。

若要刷新值,请选择刷新图标,或按空格键。 调试器尝试重新评估表达式。 然而,您可能不想或无法重新计算表达式,这取决于为什么该值没有被计算。

将鼠标悬停在刷新图标上或查看 列,原因是未计算表达式。 原因包括:

  • 计算表达式时出错,如上一示例中所示。 可能会发生超时,或者变量可能超出作用域。

  • 表达式具有一个函数调用,可在应用中触发副作用。 请参阅 表达式副作用

  • 自动评估属性和隐式函数调用已禁用。

如果刷新图标由于属性和隐式函数调用的自动评估被禁用而出现,则可以从“工具>菜单更新调试设置。

若要演示如何使用刷新图标,

  1. “工具”(或调试)>选项窗格中的“所有设置>>”部分下,清除“启用属性评估”和其他隐式函数调用复选框。
  1. “工具 ”(或 调试) >选项 对话框中的 “调试>常规 ”部分下,清除 “启用属性评估”和其他隐式函数调用 复选框。
  1. 输入以下代码,然后在 监视 窗口中对 list.Count 属性设置监视。

    static void Main(string[] args)
    {
        List<string> list = new List<string>();
        list.Add("hello");
        list.Add("goodbye");
    }
    
  2. 开始调试。 “ 监视 ”窗口显示类似于以下消息的内容:

    Refresh Watch的屏幕截图。

    Refresh Watch 的屏幕截图。

  3. 若要刷新值,请选择刷新图标,或按空格键。 调试器重新评估表达式。

表达式副作用

评估一些表达式可能会更改变量值,或者影响应用的状态。 例如,计算以下表达式会更改var1的值:

var1 = var2

此代码可能会导致 副作用。 副作用可以通过更改应用运行方式来使调试更加困难。

首次输入时,只计算一次具有副作用的表达式。 之后,表达式在 “监视” 窗口中灰色显示,并禁用进一步的评估。 工具提示或 列说明表达式会导致副作用。 可以通过选择值旁边的刷新图标来强制重新评估。

防止副作用指定的方法之一是关闭自动函数评估。 在“工具”(或调试)>选项窗格中的“所有设置>>”部分下,清除“启用属性评估”和其他隐式函数调用复选框。

防止副作用指定的方法之一是关闭自动函数评估。 在 “工具 ”(或 调试) >选项 对话框中的 “调试>常规 ”部分下,清除 “启用属性评估”和其他隐式函数调用 复选框。

仅对于 C#,当属性或隐式函数调用的求值被关闭时,可以通过在Watch窗口中的变量Name上添加ac格式修饰符来强制进行求值。 请参阅 C# 中的格式说明符

在“监视”窗口中使用对象 ID(C# 和 Visual Basic)

有时你想要观察特定对象的行为。 例如,你可能想要跟踪在该变量退出范围后由局部变量引用的对象。 在 C# 和 Visual Basic 中,可以为引用类型的特定实例创建对象 ID,并在 “监视 ”窗口和断点条件中使用它们。 对象 ID 由公共语言运行时 (CLR) 调试服务生成,并与对象关联。

注释

对象 ID 创建的弱引用不会阻止对象被垃圾收集。 它们仅适用于当前调试会话。

在以下代码中,该方法 MakePerson() 使用局部变量创建一个 Person

class Person
{
    public Person(string name)
    {
        Name = name;
    }
    public string Name { get; set; }
}

public class Program
{
    static List<Person> _people = new List<Person>();
    public static void Main(string[] args)
    {
        MakePerson();
        DoSomething();
    }

    private static void MakePerson()
    {
        var p = new Person("Bob");
        _people.Add(p);
    }

    private static void DoSomething()
    {
        // more processing
         Console.WriteLine("done");
    }
}

要找出DoSomething(),可以在监视窗口中添加对Person对象 ID 的引用。

  1. 创建 Person 对象后,在代码中设置断点。

  2. 开始调试。

  3. 当执行在断点处暂停时,通过选择“调试>>”打开“局部变量”窗口。

  4. 在“ 局部变量 ”窗口中,右键单击变量 Person 并选择“ 生成对象 ID”。

    应会看到美元符号 ($) 加上 局部变量 窗口中的数字,即对象 ID。

  5. 右键单击对象 ID 并选择“添加监视”,将对象 ID 添加到“监视”窗口。

  6. DoSomething() 方法中设置另一个断点。

  7. 继续调试。 执行在DoSomething()方法中暂停时,监视窗口将显示Person对象。

    如果想要查看对象的属性,例如 Person.Name,必须启用属性评估。

    “工具”(或“调试”>选项)窗格中的“所有设置>>”部分下,选中“启用属性评估和其他隐式函数调用”复选框。

    “工具 ”(或 调试) >选项 对话框中的 “调试>常规 ”部分下,选中“ 启用属性计算和其他隐式函数调用 ”复选框。

动态视图和监视窗口

某些脚本语言(例如 JavaScript 或 Python)使用动态或鸭子类型,而 .NET 4.0 及更高版本支持那些在正常调试窗口中难以观察的对象。

监视 ”窗口将这些对象显示为动态对象,这些对象是从实现 IDynamicMetaObjectProvider 接口的类型创建的。 动态对象节点显示动态对象的动态成员,但不允许编辑成员值。

若要刷新 动态视图 值,请选择动态对象节点旁边的 刷新图标

若要仅显示对象的动态视图,请在“监视”窗口中的动态对象名称后面添加动态格式说明符:

  • 对于 C#: ObjectName, dynamic
  • 对于 Visual Basic: $dynamic, ObjectName

注释

  • 当你单步执行下一行代码时,C# 调试器不会自动重新评估 动态视图中 的值。
  • Visual Basic 调试器会自动刷新通过 动态视图添加的表达式。
  • 评估 动态视图 的成员可能会带来 副作用

要插入一个将对象转换为动态对象的新监视变量,请执行以下步骤:

  1. 右键单击 动态视图的任何子节点。
  2. 选择 添加监视。 变为object.name((dynamic) object).name并显示在新的“监视”窗口中。

调试器还会将对象的 动态视图 子节点添加到 “自动” 窗口。 若要打开 “自动 ”窗口,请在调试期间选择“ 调试>Windows>自动”。

动态视图 还增强了 COM 对象的调试。 当调试器处理包装在 System.__ComObject 中的 COM 对象时,它会为该对象添加一个 动态视图 节点。

使用 QuickWatch 观察单个变量或表达式

可以使用 QuickWatch 观察单个变量。

例如,对于以下代码:

static void Main(string[] args)
{
    int a, b;
    a = 1;
    b = 2;
    for (int i = 0; i < 10; i++)
    {
        a = a + b;
    }
}

观察a变量,

  1. a = a + b; 行上设置断点。

  2. 开始调试。 执行在断点处暂停。

  3. 在代码中选择变量 a

  4. 选择 调试>快速监视,按下 Shift+F9,或右键单击并选择快速监视

    此时会显示 “快速监视 ”对话框。 变量a位于值为1表达式框中。

    QuickWatch 变量的屏幕截图。

    QuickWatch 变量的屏幕截图。

  5. 若要使用变量计算表达式,请在a + b”框中键入表达式,然后选择“重新计算”。

    QuickWatch 表达式的屏幕截图。

    QuickWatch 表达式的屏幕截图。

  6. 若要将“ 快速监视 ”中的变量或表达式添加到 “监视 ”窗口,请选择“ 添加监视”。

  7. 选择 “关闭 ”以关闭 “快速监视 ”窗口。 (QuickWatch 是一个模式对话框,因此只要打开,就不能继续调试。

  8. 继续调试。 可以在 “监视 ”窗口中观察变量。

获取 AI 帮助

如果你有 Copilot,可以在查看“监视”窗口中的变量时获得 AI 帮助。 右键单击变量,并使用Ask Copilot按钮。 在此方案中,Copilot 已经知道你的问题的上下文,因此你无需自己在聊天中提供上下文。 有关详细信息,请参阅使用 Copilot 进行调试