学会使用C#异常
作者:反骨仔(二五仔) 发布时间:2021-08-17 23:31:19
在 C# 中,程序中在运行时出现的错误,会不断在程序中进行传播,这种机制称为“异常”。异常通常由错误的代码引发,并由能够更正错误的代码进行 catch。异常可由 .NET 的 CLR 或由程序中的代码引发。一旦引发了异常,这个异常将会在调用堆栈中一直向上进行传播,直到寻找到跟它匹配的 catch 语句。没有 catch 的异常会由系统提供的默认的异常处理程序进行处理,也就是你经常看到的一个突然造成调试中断并显示异常信息的对话框。
所有的异常,它们都是从 Exception 派生出来的。这些异常的类型,都会包含详细描述异常的属性。在这里我将自定义了一个新的异常类,其实也可以自定义配置异常的属性(这是可选的),然后我使用 throw 关键字显示引发该对象(即异常)。
/// <summary>
/// 定义新异常
/// </summary>
class MyException : Exception
{
public MyException(string msg) { }
}
/// <summary>
/// 抛出新定义的异常
/// </summary>
static void ThrowMyExcetion()
{
throw new MyException("Sorry, this is test!");
}
在引发异常之后,运行时程序会检查当前语句确定它是否包含在 try 块中。 如果是的话,就会检查与该 try 块相关联的所有 catch 块,来确定它们是否能够 catch 该异常。 catch 块通常会指定异常类型;如果该 catch 块的类型与异常或它的基类的相同(或匹配),则该 catch 块就能够捕获并处理。
static void Main(string[] args)
{
try
{
ThrowMyExcetion(); //直接调用抛出异常的方法
}
catch (MyException e)
{
Console.WriteLine(e);
}
Console.Read();
}
如果引发异常的语句不在 try 块中,或者包含该语句的 try 块没有匹配的 catch 块,运行时将检查调用方法中是否有 try 语句和 catch 块。 运行时将在调用堆栈中继续往上搜索兼容(或匹配)的 catch 块。在找到并执行 catch 块之后,控制权将传递给 catch 块之后的下一个语句。
一个 try 语句可能包含多个 catch 块。 将执行第一个能够处理该异常的 catch 语句;任何后续的 catch 语句都将被忽略,即使它们是兼容的也如此。 因此,在任何情况下都应该按照从最具体(或者派生程度最高)到最不具体这一顺序排列 catch 块。 例如:
static void Main(string[] args)
{
StreamWriter sw = null;
try
{
sw = new StreamWriter(@"C:\book\小二和小三的故事.txt");
sw.Write("You are 250.");
}
catch (FileNotFoundException e)
{
//将具体的异常放在第一位
Console.WriteLine(e);
}
catch (IOException e)
{
//将并不具体的放在相对后面的位置
Console.WriteLine(e);
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
if (sw != null)
{
sw.Close();
}
}
Console.Read();
}
执行 catch 块之前,运行时会检查 finally 块。 Finally 块使程序员能够清除中止的 try 块可能遗留下的任何模糊状态,或者释放任何外部资源(例如图形句柄、数据库连接或文件流),而无需等待运行时中的垃圾回收器终结这些对象。 例如:
static void Main(string[] args)
{
FileStream fs = null;
FileInfo fi = new FileInfo(@"小二和小三的故事.txt");
try
{
fs = fi.OpenWrite();
fs.WriteByte(0);
}
finally
{
//记住哦,如果你忘记 close,将会引发 IO 异常!
//if (fs != null)
//{
// fs.Close();
//}
}
try
{
fs = fi.OpenWrite();
fs.WriteByte(1);
Console.WriteLine("OK!");
}
catch (IOException e)
{
Console.WriteLine("Fail!");
}
Console.Read();
}
“Fail!”,这是因为上面注释了需要关闭文件流的语句,你可以尝试下去掉注释看看结果,记住哦,IO 操作都应该在结束时释放资源。
如果 WriteByte(0)(第9行) 引发了异常,那么在没有调用 fs.Close() 的情况下,你在第二个 try 块中尝试重新 OpenWrit() 的代码就会失败,因为此时文件会保持锁定状态。 假如你取消注释,由于会执行 finally 块(即使已引发异常),使得可以正确地关闭文件,从而避免再次引发异常。
如果在引发异常之后没有在调用堆栈上找到相匹配的 catch 块,则会可能会出现下面的情况:
如果异常出现在析构函数中,则中止该析构函数并调用基类的析构函数(如果有)。
如果调用堆栈包含静态构造函数或静态字段初始值设定项,则会引发 TypeInitializationException,并将原始异常分配给新异常的 InnerException 属性。
如果到达线程的开头,将会终止线程。
来源:http://www.cnblogs.com/liqingwen/p/6193534.html
猜你喜欢
- java * 的方法总结AOP的拦截功能是由java中的 * 来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该
- 基于 springboot+vue 的测试平台(练手项目)开发继续更新。接下来准备开发请求断言功能。关于这个功能要实现哪些需求,长什么样子,
- 本文实例为大家分享了Java使用poi操作excel的具体代码,供大家参考,具体内容如下依赖poi的jar包,pom.xml配置如下:<
- 我们讲一下Criteria查询,这个对于不是太熟悉SQL语句的我们这些程序员来说是很容易上手的。 废话不多说,看一下例子:&nbs
- 直接插入排序直接插入排序的思路很容易理解,它是这样的:1.把待排序的数组分成已排序和未排序两部分,初始的时候把第一个元素认为是已排好序的。2
- 本文实例讲述了Java设计模式之工厂模式实现方法。分享给大家供大家参考,具体如下:工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体
- 一、位运算的分类与展现效果java位运算可以分为左移和右移,其中右移还有无符号右移。 java只对整型位移,可以分为int体系和long体系
- static表示“全局”或者“静态”的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概
- java身份证合法性校验并获取身份证号有效信息,供大家参考,具体内容如下java身份证合法性校验/**身份证前6位【ABCDEF】为行政区划
- monitor概念管程,监视器。在操作系统中,存在着semaphore和mutex,即信号量和互斥量,使用基本的mutex进行开发时,需要小
- Spring EL表达式语言,支持在XML和注解中表达式,类是于JSP的EL表达式语言。在Spring开发中经常涉及调用各种资源的情况,包含
- Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecim
- Servlet3.0的出现是servlet史上最大的变革,其中的许多新特性大大的简化了web应用的开发,为广大劳苦的程序员减轻了压力,提高了
- 二分查找又称折半查找,它是一种效率较高的查找方法。折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以
- 前言异步调用几乎是处理高并发,解决性能问题常用的手段,如何开启异步调用?SpringBoot中提供了非常简单的方式,就是一个注解@Async
- 1、反射的概念1、概念反射,指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对任意一个对象,都能调用它的任意一个方法。这种
- 一、简介Android的消息机制主要是指Handler的运行机制,那么什么是Handler的运行机制那?通俗的来讲就是,使用Handler将
- 使用maven的profile功能,我们可以实现多环境配置文件的动态切换,可参考我的上一篇博客。但随着SpringBoot项目越来越火,越来
- 在Java的学习中,涉及到两个系统环境变量path和classpath一. path环境变量path环境变量是系统环境变量的一种,它用于保存
- 今天介绍一个实用的小知识点,如何将List转为Map<Object, List<Object>>1. 基本写法最开始