C# 中的错误处理:try/catch 及其他
错误处理是可靠软件的关键组成部分之一。在 C# 中,为此目的使用了异常机制(exceptions)。正确使用 try、catch 和 finally 结构不仅可以避免程序意外终止,还能使代码更具可读性和可预测性。在本文中,我们将分析异常处理的基础知识、最佳实践以及 .NET 平台提供的高级功能。
1. 基本 try/catch/finally 块
C# 中错误处理的主要工具是 try-catch-finally 块。其语法直观易懂:
- try — 包含可能抛出异常的代码。
- catch — 捕获并处理异常。
- finally — 无论是否发生异常,始终执行。用于释放资源(关闭文件、数据库连接)。
让我们看一个简单的例子——除以零:
using System;
class Program{ static void Main() { try { int a = 10; int b = 0; int result = a / b; // 这里将引发异常 Console.WriteLine($"结果: {result}"); } catch (DivideByZeroException ex) { Console.WriteLine($"错误: {ex.Message}"); } finally { Console.WriteLine("finally 块已执行。"); } }}程序输出:
错误: 尝试除以零。finally 块已执行。请注意:如果不指定具体的异常类型,catch 块将捕获所有异常。这可能很方便,但通常被认为是不好的实践,因为它会隐藏实际问题。
2. 异常类型及其层次结构
在 C# 中,所有异常都继承自基类 System.Exception。最常用的有:
SystemException— 系统异常的基类。NullReferenceException— 访问值为null的对象。IndexOutOfRangeException— 数组索引越界。InvalidOperationException— 在无效状态下调用方法。ArgumentException及其派生类(ArgumentNullException、ArgumentOutOfRangeException)— 方法参数无效。
您可以在一个 catch 块中捕获多种异常类型(从 C# 6 开始):
try{ // 代码}catch (ArgumentNullException ex) when (ex.ParamName == "userId"){ Console.WriteLine("参数 userId 不能为 null。");}catch (InvalidOperationException ex){ Console.WriteLine($"无效操作: {ex.Message}");}catch (Exception ex) when (Log(ex, "未知错误")){ // 异常过滤器——仅当条件为真时执行该块 throw; // 重新抛出异常}异常过滤器(when 关键字)允许更灵活地控制处理逻辑,同时不会丢失调用堆栈。
3. 生成自定义异常
有时标准异常不够用。您可以通过继承 Exception 来创建自己的异常类:
public class InvalidAgeException : Exception{ public int Age { get; }
public InvalidAgeException(int age, string message) : base(message) { Age = age; }
public InvalidAgeException(int age, string message, Exception inner) : base(message, inner) { Age = age; }}现在