练习 - 实现 try-catch 异常处理

已完成

try-catch 模式包含一个 try 块,后跟一个或多个 catch 子句。 每个 catch 子句指定不同异常类型的处理程序。

引发异常时,公共语言运行时(CLR)将搜索能够处理该异常的catch子句。 如果当前正在执行的方法不包含 catch 可以处理引发的异常类型的子句,则 CLR 将搜索调用当前方法的方法。 搜索将沿调用堆栈向下进行,直到找到合适的 catch 子句。 catch如果未找到任何子句来处理异常,则 CLR 向用户显示未经处理的异常消息,并停止执行程序。

在本练习中,你将实现基本 try-catch 模式。

创建新的代码项目

第一步是创建在本模块中使用的代码项目。

  1. 打开一个新的 Visual Studio Code 实例。

  2. 在“文件”菜单中,选择“打开文件夹”

  3. “打开文件夹 ”对话框中,导航到 Windows 桌面 文件夹。

  4. “打开文件夹 ”对话框中,选择“ 新建文件夹”。

  5. 将新文件夹命名 为 Exceptions101,然后选择“ 选择文件夹”。

  6. 在“终端”菜单中,选择“新终端”。

    你将使用 .NET CLI 命令创建新的控制台应用。

  7. 在终端面板命令提示符处,输入以下命令:

    dotnet new console
    
  8. 关闭“终端”面板。

实现简单的 try-catch

  1. 使用 Visual Studio Code EXPLORER 视图打开Program.cs文件。

  2. 在“视图”菜单中,选择“命令面板”

  3. 在命令提示符下,输入 .net:g,然后选择 .NET:生成构建和调试的资产

  4. 将Program.cs文件的内容替换为以下代码:

    double float1 = 3000.0;
    double float2 = 0.0;
    int number1 = 3000;
    int number2 = 0;
    
    Console.WriteLine(float1 / float2);
    Console.WriteLine(number1 / number2);
    Console.WriteLine("Exit program");
    
  5. 花点时间检查代码。

    请注意,应用程序使用两种数值变量类型, double 以及 int。 该代码使用这两种数值类型执行除法计算。

    当精确小数值很重要时,开发人员使用 double 类型变量进行计算。

  6. 在“运行”菜单上,选择“开始调试”

    请注意, DivideByZeroException 将整数值除以时发生异常。

    注释

    你可能已注意到,使用类型的 double 变量的公式能够完成,而不会导致错误。 使用 double 类型变量进行除以零计算时,将返回等于正无穷大、负无穷大或“非数字”的结果。 这并不意味着应始终使用double类型变量,而不是使用intdecimal类型变量。 正确的方法是使用适当类型的变量并实现异常处理来捕获可能发生的任何错误。

  7. “调试”工具栏上,选择“ 继续”。

    显示“调试”工具栏上的“继续”按钮的屏幕截图。

  8. 花一分钟时间检查应用程序的消息输出。

    ∞
    Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
       at Program.<Main>$(String[] args) in C:\Users\msuser\Desktop\Exceptions101\Program.cs:line 7
    

    请注意,未经处理的异常导致应用程序在第一个 Console.WriteLine() 语句完成后关闭。

    注释

    默认情况下,Visual Studio Code 使用不同的颜色文本来显示调试器生成的消息。 这有助于开发人员区分应用程序输出和调试器消息。 如果想要更清晰地查看应用程序的输出,可以将 launch.json 文件配置为使用其他控制台。 例如,将console设置为integratedTerminal,以使用终端面板来输出应用程序。 调试器消息始终显示在“调试控制台”面板中。

  9. 将这两个计算括在 try 语句的代码块中,如下所示:

    double float1 = 3000.0;
    double float2 = 0.0;
    int number1 = 3000;
    int number2 = 0;
    
    try
    {
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    
    Console.WriteLine("Exit program");
    
  10. 请注意 try 块右括号下的红色波浪线。

    要使用try语句时,C# 语法需要一个catchfinally子句。

  11. try代码块下面构造一个catch代码块,如下所示:

    try
    {
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    catch
    {
        Console.WriteLine("An exception has been caught");
    }
    
  12. 在 Visual Studio Code 的“文件”菜单上,选择“保存”。

  13. 在“运行”菜单上,选择“开始调试”

  14. 花一分钟时间检查应用程序生成的输出。

    ∞
    An exception has been caught
    Exit program
    
  15. 请注意,尽管异常仍然存在,但应用程序现在可以在关闭之前完成剩余代码行的执行。

    异常处理使你能够在发生异常时控制代码执行。 异常处理有助于确保代码稳定并生成预期结果。

捕获调用方法中引发的异常

在许多情况下,异常是在调用堆栈的某个级别捕获的,该级别低于引发异常的级别。

引发异常且当前方法不捕获异常时,公共语言运行时将展开堆栈,查找包含 catch 可处理异常的子句的方法。 将执行可以处理异常的第一个 catch 子句。 如果在调用堆栈中的任何位置都找不到适当的 catch 子句,公共语言运行时将终止进程并向用户显示错误消息。

  1. 将Program.cs文件中的代码替换为以下代码:

    try
    {
        Process1();
    }
    catch
    {
        Console.WriteLine("An exception has occurred");
    }
    
    Console.WriteLine("Exit program");
    
    static void Process1()
    {
        WriteMessage();
    }
    
    static void WriteMessage()
    {
        double float1 = 3000.0;
        double float2 = 0.0;
        int number1 = 3000;
        int number2 = 0;
    
        Console.WriteLine(float1 / float2);
        Console.WriteLine(number1 / number2);
    }
    
  2. 花一分钟时间查看更新的代码。

    • 顶级语句包括调用Process1()方法的try代码块。
    • Process1() 方法调用 WriteMessage() 方法。
    • 方法 WriteMessage() 包含将抛出异常 DivideByZeroException 的代码。

    请注意,异常将在调用栈中位于 try 代码块和 catch 代码块两层之上的方法中生成。

    显示引发异常和捕获异常之间的调用堆栈级别的屏幕截图。

    顶级语句在调用堆栈中表示为一个名为 Main 的方法。

  3. 在 Visual Studio Code 的“文件”菜单上,选择“保存”。

  4. 在“运行”菜单上,选择“开始调试”

  5. 花一分钟时间检查应用程序生成的输出。

    ∞
    An exception has occurred
    Exit program
    
  6. 请注意,即使异常被抛到调用堆栈上两层,仍然能够成功处理。

回顾

在本单元中,应谨记以下几个重要事项:

  • 为应用程序中的 try 指定代码行和 try 代码块范围内发生的 catch 异常实现 try-catch 模式。
  • 使用 catch 子句捕获在同一调用堆栈级别引发的异常。
  • 使用catch语句来捕获在调用堆栈更高级别引发的异常。