认识C#程序中的异常以及异常处理原则

文章目录

一、.NET Framwork程序中的异常

1.1为什么要使用异常

异常提供了一种结构化的错误处理机制,使得错误检测和处理可以和正常的程序逻辑分离。使用异常有以下优点:

  1. 清晰的错误管理:异常处理允许程序员将错误检测与处理代码分离,减少程序的复杂性。
  2. 错误传播:异常可以在调用堆栈中向上抛出,直到它们被捕获为止,使得方法调用者可以选择性地处理错误。
  3. 类型安全:异常是类型化的,这意味着可以根据不同的错误类型来捕捉和处理不同的异常。
  4. 管理资源 :使用finally块或者using语句块,可以确保即使在发生错误的情况下,也能释放资源,如文件句柄、网络连接、数据库连接等。
  5. 异常包含丰富信息:异常对象包含很多有助于错误诊断和处理的信息,如错误消息、堆栈跟踪、错误代码等。

1.2 异常的常见类型:

.NET中的异常有很多,但这里列出了一些最常见的异常类型:

  1. System.Exception:所有异常的基类。
  2. System.SystemException :从System.Exception派生的用于系统异常的基类。
  3. System.NullReferenceException:尝试访问空引用时抛出。
  4. System.InvalidOperationException:当方法调用对于对象的当前状态无效时抛出。
  5. System.ArgumentException:非法参数引发的异常的基类。
  6. System.ArgumentNullException :当传递给方法的参数为null时抛出。
  7. System.ArgumentOutOfRangeException:当传递给方法的参数超出有效值范围时抛出。
  8. System.IndexOutOfRangeException:当尝试访问集合中的索引而该索引超出范围时抛出。
  9. System.FormatException:当格式不正确或格式化操作失败时抛出。
  10. System.IO.IOException:涉及I/O操作(如使用文件、网络等)失败或被中断时抛出。
  11. System.NotSupportedException:当调用的方法不被支持或尚未实现时抛出。
  12. System.InvalidCastException:显式类型转换操作失败时抛出。
  13. System.OutOfMemoryException:没有足够的内存继续执行程序时抛出。
  14. System.StackOverflowException:执行的方法递归太深导致堆栈溢出时抛出(注意,这通常被视为不可恢复的情况)。
  15. System.DivideByZeroException:尝试除以零时抛出。

使用异常处理机制时,很重要的一点是只处理那些你确实可以处理的异常情况,避免捕获太广泛的异常类型,这可能会掩盖一些应当被发现的错误。

1.3 了解.NET Framwork的异常设计架构

在.NET Framework中,异常处理是通过使用一组关键字(try、catch、finally 和 throw)在运行时对错误进行检测和处理的一种方式。异常处理架构是基于下面几个核心概念设计的:

System.Exception 基类

所有异常都派生自System.Exception类。这个基类提供了几个重要的属性,如Message、StackTrace、InnerException等,这些属性给出了关于异常的详细信息。

异常类层次结构

.NET Framework定义了一个异常类的层次结构,这样就可以通过捕获特定类型的异常来对不同的错误条件作出响应。例如,System.IO.IOException是处理与输入/输出操作相关的异常,而System.IndexOutOfRangeException用于处理访问数组时索引超出其界限的情况。

try 块

try块用于定义可能会引发异常的代码段。如果在try块中的代码抛出异常,控制流将跳转到后续的catch块。

catch 块

catch块跟在try块后面,并定义了一系列的异常处理程序。每个catch块针对一个特定的异常类型(或所有异常,如果没有指定类型)。当异常被抛出时,运行时会查找匹配的catch块来处理它。

我们可以有多个catch块来捕获不同类型的异常,它们应该从最具体到最一般的顺序排列。

finally 块

finally块是可选的,用于执行无论是否发生异常都需要执行的清理代码。即使try或catch块中有return语句,finally块中的代码也会执行。

throw 关键字

throw关键字用于抛出异常。你可以重新抛出当前处理的异常,或者抛出一个新的异常实例。

示例

以下是一个C#中使用异常处理的简单示例:

csharp 复制代码
try
{
    // 试图执行可能会抛出异常的代码
    int[] numbers = { 1, 2, 3 };
    Console.WriteLine(numbers[3]); // 这将引发IndexOutOfRangeException(异常类型,这种异常在尝试访问数组、集合或列表等类型的元素时,如果使用的索引超出了实际的范围,就会被抛出。)
}
catch (IndexOutOfRangeException ex)
{
    // 捕获并处理特定类型的异常
    Console.WriteLine("An index out of range exception occurred: " + ex.Message);
}
catch (Exception ex)
{
    // 捕获并处理所有其他类型的异常
    Console.WriteLine("An unexpected error occurred: " + ex.Message);
}
finally
{
    // 清理代码,在这里执行
    Console.WriteLine("The 'try catch' block is finished.");
}

在这个例子中,如果访问数组的索引超出了范围,将会触发IndexOutOfRangeException,这个异常会被第一个catch块捕获并处理。finally块中的代码无论是否发生异常都会执行,用于执行清理工作。如果异常类型不匹配IndexOutOfRangeException,那么会被第二个catch块捕获。

二、总结

异常处理原则

  1. 精确捕获:

    • 应该尽可能精确地捕获异常,避免使用过于宽泛的 catch。
    • 捕获你实际可以处理的异常,如果你不能处理它,让它传递给调用堆栈中更合适的层次。
  2. 避免空的catch块:

    • 捕获异常后不进行任何处理是不推荐的,这会隐藏错误并使调试变得困难。
  3. 使用finally释放资源:

    • 对于需要释放的资源,如文件句柄或数据库连接,使用 finally 块确保即使发生异常也能够释放资源。
  4. 异常具体化:

    • 抛出异常时,提供足够的信息,如错误消息和内部异常,以便于理解发生了什么问题。
  5. 不要用异常控制流程:

    • 异常应该用于异常情况,而不是用来控制程序的正常流程。
  6. 最小化try块的代码量:

    • try 块中应该只包含可能抛出异常的代码,这有助于减少错误发生的范围,并使 try-catch 结构更清晰。
  7. 抛出正确的异常类型:

    • 抛出描述错误情况的最准确的异常类型。
  8. 保守的catch:

    • 只捕获你知道如何恢复的异常。过于宽泛的捕获,例如捕获 System.Exception 或 System.SystemException,应该避免。
相关推荐
nice_lcj5209 小时前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
紧跟先前的步伐10 小时前
Go AI Agent 实战 28|Agent 的预算、超时与停止条件
开发语言·人工智能·后端·ai·golang
bksczm11 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
春涧草茶11 小时前
慢就是快16-1协程
开发语言·前端·python
Dovis(誓平步青云)12 小时前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
做科研的周师兄12 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
.痞老板.13 小时前
java ee--计算机是如何工作的
java·开发语言·java-ee
奇树谦13 小时前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构
青梅味猪大肠13 小时前
【操作系统-60】临近适应算法
java·linux·开发语言·嵌入式硬件·算法·操作系统
宝桥南山13 小时前
.NET 11 - 尝试一下Blazor中的新特性SupplyParameterFromTempData
microsoft·微软·c#·asp.net·.net·.netcore