如何在C#中捕获多个异常:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

一次性捕获:如何在C#中捕获多个异常而不重复代码

\n\n

想象一下:您正在编写一个处理文件、网络和数据库的应用程序。在一个方法中,可能会抛出FileNotFoundException、IOException或UnauthorizedAccessException。传统方法是使用三个catch块,内部包含相同的代码。这违反了DRY(不要重复自己)原则,并使代码变成“意大利面条”。

\n\n

好消息是:在C#中有几种优雅的方法可以一次性捕获多个异常。在本教程中,我们将从基础到高级逐一介绍所有方案,您将学习如何编写干净、可维护的错误处理代码。

\n\n

为什么这很重要?真实场景

\n\n

假设您正在开发一个用于备份的控制台应用程序。它读取文件、压缩文件并将其发送到远程服务器。在每个阶段都可能发生不同的异常:

\n\n
    \n
  • 读取文件: FileNotFoundException、PathTooLongException
  • \n
  • 压缩: OutOfMemoryException
  • \n
  • 发送: HttpRequestException、TimeoutException
  • \n
\n\n

如果您为每个异常编写单独的catch块并包含相同的日志记录代码,代码将变得臃肿。如果以后需要更改逻辑,则必须在三个地方进行修改。这正是学会一次捕获多个异常的价值所在。

\n\n

方法1. 经典方法:多个catch块(C# 6之前)

\n\n

最简单直接的方法是连续编写多个catch块。C#会根据异常类型自动选择相应的块:

\n\n
try\n{\n    // 可能抛出不同异常的代码\n    string content = File.ReadAllText(@"C:\\data\\config.txt");\n    int value = int.Parse(content);\n    await SendToServerAsync(value);\n}\ncatch (FileNotFoundException ex)\n{\n    Console.WriteLine($"文件未找到:{ex.Message}");\n    LogError(ex);\n}\ncatch (FormatException ex)\n{\n    Console.WriteLine($"数据格式无效:{ex.Message}");\n    LogError(ex);\n}\ncatch (HttpRequestException ex)\n{\n    Console.WriteLine($"网络错误:{ex.Message}");\n    LogError(ex);\n}
\n\n

优点:清晰易懂,可以针对每个异常进行不同处理。
\n缺点:如果操作相同,则会导致代码重复。

\n\n

方法2. 在单个catch中捕获多个异常(C# 6+)

\n\n

从C# 6开始,您可以在一个catch块中使用|列出多个异常类型。这减少了重复并保持了可读性:

\n\n
try\n{\n    // 有风险的代码\n}\ncatch (FileNotFoundException | FormatException | HttpRequestException ex)\n{\n    Console.WriteLine($"发生错误:{ex.Message}");\n    LogError(ex);\n    // 对所有三种类型通用的额外逻辑\n}
\n\n

重要提示:所有异常在层次结构上必须兼容。例如,不能混合IOException和NullReferenceException——它们除了Exception之外没有共同的基类。但在C# 6+中这是允许的,编译器会将变量ex转换为通用基类型。

\n\n

何时使用这种方法?

\n
    \n
  • 当所有异常的处理逻辑相同时。
  • \n
  • 当您希望避免嵌套的if或switch块时。
  • \n
  • 在需要简洁性的小方法中。
  • \n
\n\n

方法3. 异常过滤器(C# 6+)

\n\n

异常过滤器是一种强大的机制,允许您使用when关键字根据条件捕获异常。您可以捕获同一个异常,但根据其属性采用不同的逻辑:

\n\n
try\n{                

博客

书籍推荐