教程:了解如何使用 Visual Studio 调试 C# 代码
本文介绍分步演练中 Visual Studio 调试器的功能。 如果想要更高级别的调试器功能视图,请参阅 首先查看调试器。 当你调试应用时,通常意味着运行附带有调试器的应用程序。 执行此任务时,调试器提供了多种方式来查看代码在运行时执行的操作。 可以单步执行代码并查看变量中存储的值,可以设置对变量的监视以查看何时更改值,可以检查代码的执行路径,查看代码的分支是否正在运行,等等。 如果本练习是你第一次尝试调试代码,建议先阅读 绝对初学者调试指南,然后再通读此文。
尽管演示应用是 C# ,但大多数功能都适用于 Visual Studio 支持的 C++、Visual Basic、F#、Python、JavaScript 和其他语言(F# 不支持编辑并继续)。F# 和 JavaScript 不支持 自动 窗口)。 屏幕截图位于 C# 中。
在本教程中,你将:
- 启动调试器并命中断点。
- 了解在调试器中逐步执行代码的命令
- 检查数据提示和调试器窗口中的变量
- 检查调用堆栈
先决条件
须安装 Visual Studio 2022 且具有“.NET 桌面开发”工作负载。
必须安装 Visual Studio 2019 和 .NET Core 跨平台开发 工作负载。
如果尚未安装 Visual Studio,请转到 Visual Studio 下载 页免费安装。
如果需要安装工作负载但已有 Visual Studio,请转到 工具>获取工具和功能...,这将打开 Visual Studio 安装程序。 Visual Studio 安装程序将启动。 选择“.NET Core 跨平台开发”工作负载,然后选择“修改”。
如果已有 Visual Studio,但未安装 .NET 桌面开发 工作负载,请转到 工具>获取工具和功能...,这将启动 Visual Studio 安装程序。 在 Visual Studio 安装程序中,选择 .NET 桌面开发 工作负载,然后选择 修改。
创建项目
首先,创建 .NET Core 控制台应用程序项目。 在添加任何内容之前,项目类型附带所需的所有模板文件!
打开 Visual Studio。 如果启动窗口未打开,请选择“文件”>“开始窗口”。
在开始窗口中,选择 创建新项目。
在 创建新项目 窗口中,在搜索框中输入 控制台。 接下来,从语言列表中选择 C#,然后从平台列表中选择 Windows。
应用语言和平台筛选器后,选择 .NET Core 的 控制台应用 模板,然后选择“下一步”。
控制台应用的 C# 模板
备注
如果未看到 控制台应用 模板,可以从 创建新项目 窗口安装它。 在“找不到所需内容?”消息中,选择“安装更多工具和功能”链接。 然后,在 Visual Studio 安装程序中,选择 .NET Core 跨平台开发 工作负荷。
在 配置新项目 窗口中,在 项目名称 框中输入 GetStartedDebugging。 然后选择 下一步。
选择建议的目标框架(.NET 8.0 或长期支持),然后选择 创建。
在 创建新项目 窗口中,在搜索框中输入 控制台。 接下来,从语言列表中选择 C#,然后从平台列表中选择 Windows。
应用语言和平台筛选器后,选择 控制台应用 模板,然后选择“下一步”。
备注
如果未看到 控制台应用 模板,可以从 创建新项目 窗口安装它。 在 “找不到你要查找的内容?” 消息中,选择 安装更多工具和功能 链接。 然后,在 Visual Studio 安装程序中,选择 .NET 桌面开发 工作负荷。
在 配置新项目 窗口中,在 项目名称 框中输入 GetStartedDebugging。 然后选择 下一步。
在“其他信息” 窗口中,确保在 框架 下拉菜单中选择 .NET 8.0,然后选择 “创建”。
Visual Studio 正在打开您的新项目。
创建应用程序
在 Program.cs中,将所有默认代码替换为以下代码:
using System;
class ArrayExample
{
static void Main()
{
char[] letters = { 'f', 'r', 'e', 'd', ' ', 's', 'm', 'i', 't', 'h'};
string name = "";
int[] a = new int[10];
for (int i = 0; i < letters.Length; i++)
{
name += letters[i];
a[i] = i + 1;
SendMessage(name, a[i]);
}
Console.ReadKey();
}
static void SendMessage(string name, int msg)
{
Console.WriteLine("Hello, " + name + "! Count to " + msg);
}
}
启动调试器!
按 F5(“调试”>“开始调试”)或调试工具栏中的“开始调试”按钮
。
F5 使用附加到应用进程的调试器启动应用,但现在我们没有执行任何特殊操作来检查代码。 因此,应用程序启动后,你就会看到这个控制台输出。
Hello, f! Count to 1 Hello, fr! Count to 2 Hello, fre! Count to 3 Hello, fred! Count to 4 Hello, fred ! Count to 5 Hello, fred s! Count to 6 Hello, fred sm! Count to 7 Hello, fred smi! Count to 8 Hello, fred smit! Count to 9 Hello, fred smith! Count to 10
在本教程中,你将使用调试器仔细了解此应用,并查看调试器功能。
按红色停止按钮停止调试器(Shift + F5)。
在控制台窗口中,按键关闭控制台窗口。
大多数情况下,我们在此处使用键盘快捷方式,因为它是执行调试器命令的快速方法。 还记录了等效命令,如工具栏或菜单命令。
若要启动调试器,请选择 F5,或选择标准工具栏中的“调试目标 ”按钮,或者从菜单栏中选择“启动调试”按钮,或从菜单栏中选择 调试>“开始调试”。
F5 使用附加到应用进程的调试器启动应用。 由于我们没有执行任何特殊操作来检查代码,因此应用将运行完成并看到控制台输出。
Hello, f! Count to 1 Hello, fr! Count to 2 Hello, fre! Count to 3 Hello, fred! Count to 4 Hello, fred ! Count to 5 Hello, fred s! Count to 6 Hello, fred sm! Count to 7 Hello, fred smi! Count to 8 Hello, fred smit! Count to 9 Hello, fred smith! Count to 10
若要停止调试器,请按 Shift+F5,或者在“调试”工具栏中选择“停止调试”按钮,或者从菜单栏中选择“调试”>“停止调试”。
在控制台窗口中,选择任意键关闭控制台窗口。
设置断点并启动调试器
在
Main
函数的for
循环中,通过单击以下代码行的左边距来设置断点:name += letters[i];
红色圆圈
出现在你设置断点的位置。
断点是可靠调试的最基本和最重要的功能之一。 断点指示 Visual Studio 应在哪里暂停运行的代码,以便可以检查变量的值、观察内存的状态,或判断代码分支是否被执行。
按 F5 或 “开始调试”按钮。
应用启动,调试器将运行到设置断点的代码行。
黄色箭头表示调试器暂停的语句,该语句也会在同一点暂停应用执行(此语句尚未执行)。
如果应用尚未运行,F5 启动调试器并在第一个断点处停止。 否则,F5 继续将应用运行到下一个断点。
当您知道代码行或要详细检查的代码部分时,断点是一项有用的功能。 有关可设置的不同类型断点(如条件断点)的信息,请参阅使用断点。
在
Main
函数的for
循环中,通过单击以下代码行的左边距来设置断点:name += letters[i];
此时会显示一个红色圆圈,可在其中设置断点。
断点是执行可靠调试所不可或缺的一项功能。 可以在希望 Visual Studio 暂停正在运行的代码的位置设置断点,以便查看变量的值或内存行为,或者知道代码分支是否正在运行。
若要开始调试,请选择 F5 ,或选择标准工具栏中的“调试目标”按钮,或者从菜单栏中选择“启动调试”按钮,或者从菜单栏中选择“调试”“调试”>“开始调试”。 应用随即启动,调试器将运行到你设置了断点的代码行。
黄色箭头指向调试器暂停的语句。 应用执行在同一时间点暂停,但尚未执行该语句。
当应用未运行时,F5 启动调试器,调试器将运行该应用,直到它到达第一个断点。 如果应用在断点处暂停,F5 将继续运行应用,直到它到达下一个断点。
当您知道要详细检查的代码行或部分时,断点是一项有用的功能。 有关可设置的各种断点(例如条件断点)的详细信息,请参阅使用断点。
使用数据提示来导航代码和检查数据
大多数情况下,我们在此处使用键盘快捷方式,因为它是在调试器中快速执行应用的好方法(如菜单命令等等效命令显示在括号中)。
在
name += letters[i]
语句上暂停代码执行时,将鼠标悬停在letters
变量上,并看到其默认值,即数组中第一个元素的值,char[10]
。允许你检查变量的功能是调试器最有用的功能之一,可通过不同的方法来执行此操作。 通常,当你尝试调试问题时,你正尝试找出变量是否存储期望它们在特定时间拥有的值。
展开
letters
变量以查看其属性,其中包括变量包含的所有元素。接下来,将鼠标悬停在
name
变量上,可以看到其当前值(一个空字符串)。按两次 F10(或选择“调试”>“单步跳过”)前进到
SendMessage
方法调用,然后再按一次 F10。F10 将调试器推进到下一个语句,而无需单步执行应用代码中的函数或方法(代码仍在执行)。 通过在
SendMessage
方法调用上按 F10,我们跳过了SendMessage
的实现代码(也许我们现在对此不感兴趣)。多按几次 F10(或“调试”>“单步跳过”),通过
for
循环执行多次循环访问,再次在断点处暂停,每次都将鼠标悬停在name
变量上以检查其值。变量的值随
for
循环的每个迭代而更改,其中显示了f
、fr
、fre
等值。 若要在此情景下加快调试器通过循环的速度,可以按 F5(或选择 调试>继续),这样可以直接转到断点,而不是下一个语句。通常,在调试时,你可能需要一种快速的方法来检查变量的属性值,以查看它们是否存储了你期望的值,而数据提示是一个很好的工具来实现这一点。
当代码执行在
Main
方法的for
循环中保持暂停状态时,按 F11(或选择“调试”>“单步执行”),直到在SendMessage
方法调用处暂停。你应该位于以下代码行:
SendMessage(name, a[i]);
再按 F11 一次即可进入
SendMessage
方法。黄色指针会前进到
SendMessage
方法。F11 是“单步执行”命令,每按一次,应用就执行下一个语句。 F11 是最详细地检查执行流的好方法。 默认情况下,调试器跳过非用户代码(如果需要更多详细信息,请参阅 仅我的代码)。
假设你已完成了对
SendMessage
方法的检查,并且希望退出该方法但保持位于调试器中。 可以使用 Step Out 命令执行此操作。按 Shift + F11(或“调试”>“单步跳出”)。
此命令将恢复应用执行(并推进调试器),直到当前方法或函数返回。
你应当回到
Main
方法的for
循环,在SendMessage
方法调用处暂停。 有关在代码中进行移动的不同方法的详细信息,请参阅浏览调试器中的代码。
在
name += letters[i]
语句上暂停代码执行时,将鼠标悬停在letters
变量上以查看显示数组大小和元素类型的数据提示,char[10]
。备注
调试器最有用的功能之一是能够检查变量。 通常,尝试调试问题时,会尝试了解变量是否具有特定时间预期的值。 查看数据提示是进行这种检查的好办法。
展开
letters
变量以查看其所有数组元素及其值。将鼠标悬停在
name
变量上以查看其当前值,即空字符串。若要将调试器前进到下一语句,请选择 F10,或选择调试工具栏中的“单步执行”按钮,或者从菜单栏中选择 “调试”>“单步执行”。 再按 F10 两次以跳过
SendMessage
方法调用。按 F10 会使调试器前进,而不会单步执行函数或方法,不过,其代码仍会执行。 通过这种方式,我们跳过了在
SendMessage
方法中调试代码,而我们现在对此不感兴趣。若要多次遍历
for
循环,请重复选择 F10。 在每次循环迭代中,在断点处暂停,然后将鼠标悬停在name
变量上,以查看数据提示中的值。变量的值随
for
循环的每个迭代而更改,其中显示了f
、fr
、fre
等值。 若要使调试器在循环中更快前进,请按 F5,这样就会前进到断点而不是下一条语句。当代码执行在
Main
方法的for
循环中暂停时,请选择 F11,或者从调试工具栏中选择 单步进入 按钮,或者从菜单栏中选择 调试>单步进入,直到到达SendMessage
方法调用。调试器应在此代码行处暂停:
SendMessage(name, a[i]);
要进入
SendMessage
方法,请再次选择 F11。黄色指针会前进到
SendMessage
方法。F11 有助于更深入地检查代码的执行流。 若要单步执行方法调用中的方法,请按 F11。 默认情况下,调试器将跳过非用户方法的单步执行。 若要了解如何调试非用户代码,请参阅 “仅我的代码”。
调试完
SendMessage
方法后,即可返回到main
方法的for
循环。若要离开
SendMessage
方法,请选择 Shift+F11,或在“调试”工具栏中选择“”单步退出“ 按钮,或者从菜单栏中选择”调试“>”单步退出“。Step Out 恢复应用程序的执行并继续调试,直到当前方法或函数返回。
你将在
Main
方法的for
循环中再次看到黄色指针,该指针暂停在SendMessage
方法调用处。 有关在代码中进行移动的不同方法的详细信息,请参阅浏览调试器中的代码。
使用“运行到单击处”导航代码
选择 F5 以再次前进到断点。
在代码编辑器中向下滚动,并将鼠标悬停在
SendMessage
方法中的Console.WriteLine
方法上,直到出现绿色的“运行到单击处”按钮。 按钮的工具提示显示“将执行运行到此处”。
备注
“运行到单击处”按钮是 Visual Studio 2017 中的新增按钮。 (如果未看到绿色箭头按钮,请使用本示例中 F11,将调试器移动到正确的位置。
选择“运行到单击处”按钮。
调试器会前进到
Console.WriteLine
方法。使用此按钮类似于设置临时断点。 “运行到单击处”对于快速到达应用代码的可见区域十分方便(你可在任何打开的文件中选择)。
选择 F5 以重新前进到断点。
在代码编辑器中,将鼠标悬停在
SendMessage
方法中的Console.WriteLine
方法调用上,直到出现“运行到单击处”按钮。 按钮的工具提示显示“将执行运行到此处”。选择“运行到单击处”按钮。 或者,在
Console.WriteLine
语句处使用光标,选择 Ctrl+F10。 或者,右键单击Console.WriteLine
方法调用,然后从上下文菜单中选择“运行到光标处”。调试器会前进到
Console.WriteLine
方法调用。使用“运行到单击处”按钮类似于设置临时断点,在已打开的文件的应用代码可见区域中,可以快速方便地使用这种方法。
快速重启应用
在调试工具栏中选择“重启”按钮 (Ctrl + Shift + F5)。
按 重启时,它可以节省时间,而不是停止应用并重启调试器。 调试器在执行代码命中的第一个断点处暂停。
调试器会在之前在 for
循环中设置的断点处再次停止。
若要从调试器中开始重新运行应用,请选择 Ctrl+Shift+F5,或者 选择“调试”工具栏中的“重启”按钮,或者从菜单栏中选择“调试”>“重启”。
“重启”将通过一个步骤停止调试器并重启调试器。 当调试器重新启动时,它将运行到第一个断点,即之前在 for
循环中设置的断点,然后暂停。
使用“自动”和“局部变量”窗口检查变量
查看代码编辑器底部的“自动”窗口。
如果已关闭,请依次选择“调试”>“Windows”>“自动”,在调试器中暂停时将其打开。
在 Autos 窗口中,可以查看到变量及其当前的值。 “自动”窗口显示当前行或前一行使用的所有变量(检查文档中特定于语言的行为)。
接下来,我们来看看“自动”窗口旁边的选项卡中的“局部变量”窗口。
展开
letters
变量以显示它所包含的元素。局部变量 窗口显示当前 作用域(即当前执行上下文)中的变量。
在调试时,“自动变量”和“局部变量”窗口会显示变量值。 窗口仅在调试会话期间可用。 “自动变量”窗口显示调试器所在的当前行和上一行中使用的变量。 局部变量 窗口显示本地范围中定义的变量,通常是当前函数或方法。
在调试器处于暂停状态时,查看代码编辑器底部的“自动变量”窗口。
如果 Autos 窗口已关闭,请按 Ctrl+D、A,或者从菜单栏中选择 Debug>Windows>Autos。
在调试器仍处于暂停状态的情况下,在“自动变量”窗口旁边的选项卡中查看“局部变量”窗口。
如果局部变量 窗口已关闭,请按Ctrl+D,L,或者选择调试>Windows>局部变量。
在 局部变量 窗口中,展开
letters
变量以查看其数组元素及其值。
有关“自动变量”和“局部变量”窗口的详细信息,请参阅在“自动变量”和“局部变量”窗口中检查变量。
设置监视
在主代码编辑器窗口中,右键单击 name
变量,然后选择“添加监视”。
“监视”窗口将在代码编辑器的底部打开。 可使用“监视”窗口指定要关注的变量(或表达式)。
现在,你在 name
变量上设置了监视器,可以在调试器中移动时看到其值的变化。 与其他变量窗口不同,监视 窗口始终显示您正在监视的变量(这些变量在不属于当前作用域时将变为灰色)。
可以指定你在逐步执行代码时想要观察的变量或表达式 - 将其添加到“监视”窗口即可。
当调试器处于暂停状态时,右键单击
name
变量并选择“添加监视”。“监视”窗口默认将在代码编辑器的底部打开。
对
name
变量设置监视后,接下来请逐步执行代码,以查看name
变量值在每次for
循环迭代中的变化。与其他变量窗口不同,监视 窗口始终显示正在监视的变量。 作用域外变量显示为不可用。
有关“监视”窗口的详细信息,请参阅使用“监视”窗口监视变量。
检查调用堆栈
在
for
循环中暂停代码执行时,请选择 调用堆栈 窗口,该窗口默认在右下窗格中打开。如果已关闭,请依次选择“调试”>“Windows”>“调用堆栈”,在调试器中暂停时将其打开。
选择 F11 几次,直到看到调试器在
SendMessage
方法中暂停。 查看“调用堆栈”窗口。调用堆栈 窗口显示调用方法和函数的顺序。 上行显示当前函数(此应用中
SendMessage
方法)。 第二行显示SendMessage
是从Main
方法调用的,依次类推。备注
调用堆栈 窗口类似于 Eclipse 等 IDE 中的“调试”透视。
调用堆栈是检查和了解应用执行流的好方法。
可以双击一行代码来查看该源代码,该代码还会更改调试器正在检查的当前范围。 此操作不会使调试器前进。
还可以使用 调用堆栈 窗口中的右键单击菜单来执行其他操作。 例如,你可将断点插入到指定的函数中,使用“运行到光标处”推进调试器,然后检查源代码。 如需更多信息,请参阅 如何:检查调用堆栈。
调用堆栈 可以通过显示调用方法和函数的顺序来帮助了解应用的执行流。
调试器在
for
循环中暂停时,查看 调用堆栈 窗口,该窗口默认在代码编辑器的右下窗格中打开。如果关闭 调用堆栈 窗口,请选择 Ctrl+D、C,或者从菜单栏中选择 “调试>Windows>调用堆栈”。
在 调用堆栈 窗口中,可以看到当前
Main
方法上的黄色指针。选择 F11 几次,直到看到调试器在
SendMessage
方法中暂停。调用堆栈 窗口的上行显示当前函数,即
SendMessage
方法。 第二行显示SendMessage
方法是从Main
方法调用的。备注
调用堆栈 窗口类似于某些 IDE 中的“调试”透视,如 Eclipse。
在 调用堆栈 窗口中,可以双击一行代码转到该源代码,这会更改调试器正在检查的当前范围。 此操作不会使调试器前进。
还可以使用 调用堆栈 窗口中的右键单击菜单来执行其他操作。 例如,可将断点插入到指定的函数中、使用“运行到光标处”使调试器前进,或转到源代码。
有关 调用堆栈的详细信息,请参阅 如何:检查调用堆栈。
后续步骤
本教程介绍了如何启动调试器、逐步执行代码和检查变量。 你可能想要大致了解调试器功能以及指向详细信息的链接。