C# 错误处理:try/catch 及更多:从 A 到 Z
任何应用程序,即使是由最有经验的开发人员编写的,也可能遇到意外情况:网络故障、磁盘上缺少文件、除以零或输入数据无效。在 C# (.NET) 中,使用异常 (exceptions) 机制来管理此类情况。在本文中,我们将介绍有关错误处理所需了解的所有内容:从基本的 try/catch 结构到创建自己的异常类型和现代最佳实践。
1. 基础:try/catch/finally 结构
在 C# 中,错误处理围绕三个关键块构建:try、catch 和 finally。
- try — 包含可能引发异常的代码。
- catch — 捕获并处理特定异常。
- finally — 无论是否发生异常,始终执行(通常用于释放资源)。
try{ int[] numbers = { 1, 2, 3 }; Console.WriteLine(numbers[5]); // IndexOutOfRangeException}catch (IndexOutOfRangeException ex){ Console.WriteLine($"错误: {ex.Message}");}finally{ Console.WriteLine("Finally 块始终执行。");}您可以为不同类型的异常使用多个 catch 块。处理顺序是从上到下,因此更具体的异常应放在通用异常之上。
try{ // 危险代码}catch (DivideByZeroException ex){ Console.WriteLine("除以零!");}catch (Exception ex) // 通用捕获{ Console.WriteLine($"发生错误: {ex.Message}");}2. 引发异常:throw 运算符
有时您需要明确报告不正确的情况。为此,使用 throw 运算符。您可以抛出标准异常,也可以抛出自定义异常。
public void ValidateAge(int age){ if (age < 0 || age > 150) { throw new ArgumentOutOfRangeException(nameof(age), "年龄必须在 0 到 150 之间。"); } Console.WriteLine("年龄有效。");}还有 throw; 结构(不带参数)——它在 catch 块内部用于重新引发相同的异常。当您想记录错误但不想抑制它时,这很有用。
try{ // 代码}catch (Exception ex){ Log.Error(ex); // 写入日志 throw; // 重新引发 — 异常继续向上传播}3. 创建自定义异常
对于业务逻辑,使用自己的异常类型通常更方便。这使代码更具可读性,并允许精确处理特定错误。
创建自定义异常的规则:
- 从
Exception类继承(或从ApplicationException,但最好从Exception)。 - 实现三个标准构造函数(无参数、带消息、带消息和内部异常)。
- 建议在类名后添加
Exception后缀。
public class UserNotFoundException : Exception{ public UserNotFoundException() { }
public UserNotFoundException(string message) : base(message) { }
public UserNotFoundException(string message, Exception inner) : base(message, inner) { }}
// 使用throw new UserNotFoundException("未找到 ID 为 123 的用户。");4. 最佳实践:如何不伤害自己和项目
错误处理不仅仅是把所有代码都包在 try/catch 里。以下是几条在 C# (.NET) 中应遵守的黄金法则: