C#语言学习笔记11 —— 异常和异常处理

C#语言学习笔记11 —— 异常和异常处理

编码文章call10242025-05-18 12:27:2812A+A-

异常和异常处理

异常概述

从分类来说,异常可以由硬件产生(如除数为0),也可以由软件产生(如参数非法); 可以由内核模式下的代码产生,也可以由用户模式下的代码产生。 另外,异常还可以分为系统级别的异常和应用程序级别的异常。

和其它高级语言一样,C# 语言提供了一个结构化的、统一的、类型安全的异常处理机制。

对于 C# 语言,从代码角度,异常可来源于语言运行时(common language runtime,简称 CLR)、DotNet 自身、第三方库、应用代码本身。

C# 语言异常机制的语法

总的来说,C# 异常处理由语句(或子句) try、catch、finally、throw 等构成。

一个典型的 try 语句的语法如下所示:

异常的数据类型

C# 的异常是类型安全的,所有异常类型都直接或间接地从共同基类 System.Exception 派生。

常见的一些异常类型有:
System.ArithmeticException、
System.ArrayTypeMismatchException、
System.DivideByZeroException、
System.IndexOutOfRangeException、
System.InvalidCastException、
System.NullReferenceException、
System.OutOfMemoryException, 等等。

示例:捕获多个异常

try 子句后面可以跟多个 catch 子句,每个 catch 子句指定不同的异常类型。 捕获的时候,从前往后,依次匹配 catch 子句,条件满足即匹配成功,成功仅需一个。 因此,如果要捕获的多个异常类型,如果存在派生关系,需要把最具体的类型排在前面,最一般的类型排在后面。

示例:带有 finally 子句

try 语句可以带有一个 finally 子句。finally 子句是可选的,可以没有。 finally 子句又称终止器(termination handler),它总会被执行。 如果 try 不产生异常,执行完 try 的最后一个语句后,接着执行 finally 子句。 如果 try 产生异常,执行完对应的 catch 后,接着执行 finally 子句。 finally 常用来放置一些最后必须要执行的动作,比如释放资源等。

示例:抛出异常

使用 throw 语句抛出异常。"throw new <新的异常>;",创建新的异常并抛出; "throw;" 重新抛出当前异常。

例如,在函数中,根据条件判断,主动抛出异常:

又例如,在给属性赋非法值时抛出异常:

示例:使用自定义异常类型

要自定义一个异常类型,需要声明一个类,继承于 System.Exception,或继承于 System.Exception 的派生类。

大多数第三方类库都使用了自定义异常类型。

下面是一个使用自定义异常类型的简单例子:

示例:使用 when 异常过滤(exception filter)

在 catch 异常类型的时候,可以加上 when 表达式,当类型匹配且表达式返回 true 时,匹配成功。

同一个异常类型,可以加上不同的 when 表达式。

示例:在 async / await 中使用异常

当在 async / await 中使用异常时,需要注意一点,尽管异常可能已经在异步执行中产生,但只有在执行到 await 时, 产生的异常这时才传导过来。

示例:捕获所有异常

有些时候,我们需要在一个方法中捕获所有异常。 比如一个需要长时间运行的程序,希望不管发生什么异常,它都不终止运行。 这是,可以在应用入口函数中捕获所有异常。

为了捕获所有异常,可以采用 catch(Exception) 这种形式,因为 Exception 是所有异常的基类, 所以它能匹配所有的异常类型。或者,使用不带类型的 catch 子句。

异常机制和其它错误处理方式的比较

方式1、通过函数返回值或传出参数,传递错误信息

优点:

  1. 开销小,主要花在参数传递。
  2. 线程安全,可用于多线程环境。

缺点:

  1. 传递的方式不统一,需要文档辅助说明。
  2. 如果隔层处理错误,需要在错误处理层和错误产生层之间,层层传递同一个错误信息,比较繁琐、枯燥乏味。

方式2、通过类似全局变量的方式,传递错误信息

优点:

  1. 开销小,主要在参数传递,而且只传一次。
  2. 如果隔层处理错误,不需额外传递错误信息,可直接访问。

缺点:

  1. 非线程安全,很难甚至不能用于多线程环境。
  2. 就算是单线程、也容易因处理不当而产生错误。
  3. 只适合一些比较特殊的场景。

方式3、使用异常处理机制

优点:

  1. 处理方式统一,类型安全。
  2. 线程安全,可用于多线程环境。
  3. 错误产生和错误处理互不依赖,只需关心自己的需要,很方便。

缺点:

  1. 开销比参数传递要多一些,在异常产生时,需要保存一些调用现场,然后需要逐层检查调用堆栈,以便寻找匹配的异常处理入口。

因为异常机制有许多优点,开销其实也不算太大,实际中得到大量应用。在模块化软件设计中,更是普遍使用。所以,已经成为了一种标准。

结束语

C# 的异常处理,可以帮助开发人员方便、优雅、安全地开发软件。

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4