Csharp 使用try-catch-finally语句处理异常

在 C# 编程中,try - catch - finally语句是一种强大的机制,用于处理程序运行时可能出现的异常情况。异常是在程序执行过程中出现的错误或意外情况,例如试图访问不存在的文件、数组越界、除数为零等操作。使用try - catch - finally可以让程序在遇到这些异常时采取适当的措施,而不是直接崩溃。

try 块
功能:try块是包含可能会抛出异常的代码部分。这是异常处理的起点,当程序执行到try块中的代码时,会监控其中的操作是否会引发异常。

  • 示例:
  • 1
    2
    3
    4
    5
    try
    {
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[3]);// 这里会抛出IndexOutOfRangeException异常,因为数组最大索引是2
    }

    在这个示例中,代码试图访问数组numbers中不存在的索引(索引为 3,而数组长度为 3,有效索引范围是 0 - 2),这会导致一个IndexOutOfRangeException异常。

  • catch 块
  • 功能:catch块用于捕获try块中抛出的特定类型的异常。当try块中的代码抛出异常后,程序会查找匹配的catch块来处理该异常。可以有多个catch块,每个catch块可以处理不同类型的异常。

  • 示例:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    try
    {
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[3]);
    }
    catch (IndexOutOfRangeException ex)
    {
    Console.WriteLine("数组索引超出范围,异常信息: " + ex.Message);
    }

    在这个例子中,catch块捕获了IndexOutOfRangeException类型的异常。ex是异常对象,通过它可以访问异常的详细信息,如Message属性包含了异常的文本描述。当异常被捕获后,catch块中的代码会被执行,这里是打印出异常信息。

    finally 块,

    功能:finally块中的代码无论try块中是否抛出异常都会被执行。它通常用于清理资源,例如关闭文件、释放数据库连接、释放内存等操作,以确保程序的资源得到正确的管理。

  • 示例:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    try
    {
    FileStream fileStream = new FileStream("test.txt", FileMode.Open);
    // 这里可能会有读取文件等操作,如果出现异常,文件流应该被正确关闭
    // 假设这里有一些可能导致异常的代码,比如读取文件内容时文件格式错误
    // 具体的读取文件操作代码省略
    }
    catch (FileNotFoundException ex)
    {
    Console.WriteLine("文件未找到,异常信息: " + ex.Message);
    }
    finally
    {
    // 关闭文件流,无论是否出现异常
    if (fileStream!= null)
    {
    fileStream.Close();
    }
    }

    在这个示例中,try块尝试打开一个文件流。如果文件不存在,会抛出FileNotFoundException异常并被catch块捕获处理。无论是否出现异常,finally块中的代码都会尝试关闭文件流(这里需要注意的是,在实际代码中,更推荐使用using语句来自动管理文件流等资源,using语句在内部也使用了try - finally机制)。

    异常类型的层次结构和匹配规则

    在 C# 中,所有异常类型都派生自System.Exception类。当抛出一个异常时,catch块会按照从上到下的顺序查找匹配的异常类型来处理。

    例如,System.ArithmeticException是一个抽象类,DivideByZeroException派生自它。如果有一个try块抛出了DivideByZeroException异常,并且有一个catch块捕获System.ArithmeticException,另一个catch块捕获DivideByZeroException,那么会优先匹配DivideByZeroException的catch块,因为它是最具体的匹配。

  • 示例:
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    try
    {
    int a = 10;
    int b = 0;
    int result = a / b;
    }
    catch (DivideByZeroException ex)
    {
    Console.WriteLine("除数不能为零,异常信息: " + ex.Message);
    }
    catch (ArithmeticException ex)
    {
    Console.WriteLine("算术异常,异常信息: " + ex.Message);
    }

    在这个例子中,try块中除法运算除数为零会抛出DivideByZeroException,它会被第一个catch块捕获,而不会匹配第二个catch块,因为DivideByZeroException更具体地匹配了抛出的异常类型。