C# 图解教程 第5版 —— 第23章 异常

文章目录

    • 23.1 什么是异常
    • 23.2 try 语句
    • 23.3 异常类
    • 23.4 catch 子句
    • 23.5 异常过滤器
    • 23.6 catch 子句段
    • 23.7 finally 块
    • 23.8 为异常寻找处理程序
    • 23.9 进一步搜索
      • 23.9.1 一般法则
      • 23.9.2 搜索调用栈的示例(*)
    • 23.10 抛出异常
    • 23.11 不带异常对象的抛出
    • 23.12 throw 表达式

23.1 什么是异常

​ 异常是程序中的运行时错误,它违反了系统约束或应用程序约束,或是正常操作时不会发生的状况。如果程序没有提供处理异常的代码,系统会挂起这个程序。例如,下面的代码在试图用 0 除一个数时抛出一个异常:

image-20240113130921192 image-20240113130931943

​ 在没有异常处理程序的情况下,应用程序将停止(或者崩溃),并向用户显示非常不友好的错误消息。异常处理的目标是通过以下操作来响应异常:

  1. 在有限的几种情况下采取纠正措施,让应用程序继续运行。
  2. 记录有关异常的信息,以便开发团队可以解决该问题。
  3. 清理任何外部资源,例如可能保持打开的数据库连接。
  4. 向用户显示友好的信息。

23.2 try 语句

​ try 语句用来指明为避免出现异常而被保护的代码段,并在发生异常时提供代码处理。其包含 3 个部分组成:

  1. try 块。
  2. catch 子句。
  3. finally 块。
image-20240113131311982
图23.1 try 语句的结构

处理异常

​ 将上述代码段放在一个 try 块中,并提供一个简单的 catch 子句来捕获并处理异常。

image-20240113131404143 image-20240113131414697

23.3 异常类

​ BCL 定义了许多异常类,每一个类代表一种指定的异常类型。当一个异常发生时,CLR 创建该类型的异常对象并寻找适当的 catch 子句以处理它。

​ 所有异常类都派生自 System.Exception 类,System.Exception 类派生自 System.Object 类。

image-20240113131616192
图23.2 异常层次的结构

​ 异常对象含有只读属性,该属性提供有助于调试应用程序的异常信息。

表23.1 异常对象的一部分属性
image-20240113131830423

23.4 catch 子句

​ catch 子句处理异常,有如下 4 种形式:

image-20240113131923698
图23.3 catch 子句的 4 种形式
  • 一般 catch 子句(形式 1):能接受任何异常,但不确定引发异常的异常类型,只能进行普通处理和清理。
  • 特定 catch 子句(形式 2):把一个异常类的名称作为参数,匹配指定类或派生自它的异常类的异常。
  • 带对象的特定 catch 子句(形式 3、4):提供的异常信息最多,可以在 catch 子句块内部访问异常变量的属性,以获取异常的详细信息。
image-20240113132339051

23.5 异常过滤器

​ 形式 4 的 catch 子句是在 C# 6.0 中添加的,相较于形式 3,异常对象还需满足特定条件,该条件被称为过滤器。这允许程序员编写更小、更专一的异常处理程序,而无需再单个处理程序中包含大量 if 语句。

image-20240113132555826

​ 有关 when 子句的重要特征如下:

  • 必须包含谓词表达式(返回值为 true 或 false)。
  • 不能是异步的。
  • 不应使用任何需要长时间运行的操作。
  • 谓词表达式中发生的异常会被忽略。

23.6 catch 子句段

​ catch 子句段可以包含多个 catch 子句。

image-20240113133131889
图23.4 try 语句的 catch 子句段结构

​ 当发生异常时,系统按顺序搜索 catch 子句的列表,第一个匹配该异常对象类型的 catch 子句被执行。

  • catch 子句必须以特定顺序排列。最特定的异常类型排第一,最普通的类型排最后。
  • 如果有一个一般 catch 子句,则必须放在最后一个。
  • 不鼓励使用一般 catch 子句,因为它允许程序继续执行从而隐藏了特定错误,让程序处于一种位置的状态。

23.7 finally 块

​ 如果程序的控制流进入了带 finally 块的 try 语句,那么 finally 始终会被执行。

image-20240113133444181
图23.5 finally 块的执行

​ 即是 try 块中有 return 语句,或在 catch 块中抛出一个异常,finally 块也总是会在返回到调用代码之前执行。

image-20240113133744787

​ 上述代码在 inVal 值为 5 时也会打印 finally 块中的语句。

image-20240113133821319

23.8 为异常寻找处理程序

​ 当程序抛出异常时,系统查看该程序是否提供了异常处理程序,具体流程如下:

  • 如果在 try 块内发生了异常,系统会查看是否有任何一个 catch 子句能处理该异常。
  • 如果找到了适当的 catch 子句:
    1. 该 catch 子句被执行。
    2. 如果有 finally 块,那么它被执行;否则,继续在最后一个 catch 子句之后执行。
image-20240113134246204
图23.6 在当前 try 语句中有处理程序的异常

23.9 进一步搜索

​ 如果异常在一个没有被 try 语句保护的代码段抛出,或者如果 try 语句没有匹配的异常处理程序,系统将不得不进一步寻找匹配的处理程序。即,按顺序搜索调用栈,查看是否存在带匹配的处理程序的封装 try 块。

​ 如果异常发生在 Method2 内的 try 块内部,系统会执行如下操作:

  1. 首先查看 Method2 是否有能处理该异常的异常处理程序:
    • 如果有,Method2 处理,程序继续执行。
    • 否则,系统沿着调用栈找到 Method1,搜寻适当的处理程序。
  2. 如果 Method1 有一个适当的 catch 子句,那么系统将:
    • 回到栈顶,即 Method2 处。
    • 执行 Method2 的 finally 块,并将 Method2 弹出栈。
    • 执行 Method1 的 catch 子句和 finally 块。
  3. 如果 Method1 没有适当的 catch 子句,系统继续搜索调用栈。
image-20240113134534938
图23.7 搜索调用栈

23.9.1 一般法则

image-20240113134928143
图23.8 处理异常的一般法则

23.9.2 搜索调用栈的示例(*)

23.10 抛出异常

​ 使用 throw 语句使代码显示抛出异常,throw 语句的语法如下:

image-20240113135129478

​ 下面的代码在 try 块中进行参数 null 检查,创建并抛出 ArgumentNullException 异常。该实例在 catch 语句中被捕获,错误被打印出来。

image-20240113135200880 image-20240113135423860

23.11 不带异常对象的抛出

​ throw 语句可以在 catch 块内部不带异常对象使用。

  • 该形式重新抛出当前异常,系统会继续搜索,为该异常寻找另外的处理程序。
  • 这种形式只能用在 catch 语句内部。
image-20240113135559476 image-20240113135607676

23.12 throw 表达式

​ 代码中有些地方不允许使用语句,而只能使用表达式。C# 7.0 后,可以在只能应用表达式的地方使用 throw 表达式,其语法和 throw 语句相同。

image-20240113135912305 image-20240113135925872

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/345696.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java内置锁:深度解析lock和trylock

lock和tryLock是两种获取锁的方式,它们在处理并发问题时有所不同,lock是阻塞性的,确保只有一个线程能访问被锁资源,但可能导致线程长时间等待;而tryLock非阻塞性,若锁被占用则立即返回失败,避免…

蓝桥杯AcWing学习笔记 8-1数论的学习(上)

蓝桥杯 我的AcWing 题目及图片来自蓝桥杯C AB组辅导课 数论(上) 蓝桥杯省赛中考的数论不是很多,这里讲几个蓝桥杯常考的知识点。 欧几里得算法——辗转相除法 欧几里得算法代码: import java.util.Scanner ;public class Main…

云服务器十大服务商——云服务器哪家好用

云服务器哪家便宜?2024最新整理你要的都在这!头部云厂商阿里云、腾讯云、华为云、京东云、UCloud等都在降价,阿腾云atengyun.com分享2024年云服务器租用价格给你惊喜! 便宜云服务器阿里云腾讯云华为云 2024年便宜云服务器汇总&…

6.2 声音编辑工具GoldWave5简介(6)

3.选择【选项】|【控制器属性】命名或单击“控制器”面板上的“设置控制器属性”按钮,打开“控制器属性”对话框,将“音量”选项卡中的“麦克风”选项打上勾,使GoldWave只能录制来自麦克风的声音。如果要录制电脑内部的声音&#…

RTMP 视频数据封装

RTMP 协议 与HTTP(超文本传输协议)同样是一个基于TCP的Real Time Messaging Protocol(实时消息传输协议)。由Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的一种开放协议 。在国内被广泛的应用于直 播领域。HTTP默认端口为80,RTMP则为1935…

第8章-第6节-Java中字符流的缓冲流

1、在说正题之前,先说一个小细节,不管是字节流还是字符流都要注意这个细节,具体看这篇博文:关于Java的IO流里面的方法read()的小细节 2、字符流的缓冲流: 1)、BufferedWriter 方法名说明void newLine()写…

专业课145+合肥工业大学833信号分析与处理考研经验合工大电子信息通信

今年专业课145也是考研科目中最满意的一门,其他基本相对平平,所以这里我总结一下自己的专业课合肥工业大学833信号分析与处理的复习经验。 我所用的教材是郑君里的《信号与系统》(第三版)和高西全、丁玉美的《数字信号处理》&…

安装rlwrap库出现问题

背景:oracle的sqlplus还是那么难用,不知道为什么不打包解决这个问题,留给用户,内核硬,就是猖狂。废话不多说。下载解压rlwrap-0.46.1.tar.gz;进入/tmp/database/rlwrap-0.46.1源码包,./configure checki…

Apache Doris (六十三): Spark Doris Connector - (3)-配置型及列映射关系

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 1. Spark 操作Doris配置项

数据结构学习之顺序栈应用的案例(有效的括号)

实例要求: 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效; 有效字符串需满足的条件: 1、左括号必须用相同类型的右括号闭合; 2、左括号必须…

C++力扣题目98--验证二叉搜索树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1: 输入…

AI Table应用程序接口表的格式说明和作用

AI Table 首先全拼不是AI人工智能表,而是Application Interface Table应用程序接口表。此表按照AUTOSAR的格式规范去定义,并且使用此Excel 表格生成相应的应用软件组件Arxml文件。下面就让我们按照AUTOSAR_EXP_AIUserGuide.pdf文档官方解释描述文件去看看…