[C#] C# 知识回顾 - 学会使用异常
学会使用异常
异常:指的是我们写的程序在运行时出现了错误,并且它会不断的蔓延、传播和扩散,有点像病毒一样。
异常通常由错误的代码引发,可能是用户的错误输入,可能是一方没有按照约定来传输格式,也可能是数据传输的过程中被篡改。我们会对自己认为有可能报错的代码进行 catch ,这称为捕获异常。
一旦引发了异常,这个异常将会在调用堆栈中一直向上进行传播,直到寻找到跟它匹配的 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!");
}
在引发异常之后,CLR 运行时程序会检查当前语句确定它是否包含在 try 块中。 如果是的话,就会检查与该 try 块相关联的所有 catch 块,来确定它们是否能够 catch 该异常。如果该 catch 块的类型与异常或它的基类的相同(或匹配),则该 catch 块就能够捕获并处理。
static void Main(string[] args)
{
try
{
ThrowMyExcetion(); //直接调用抛出异常的方法
}
catch (MyException e)
{
Console.WriteLine(e);
} Console.Read();
}

如果引发异常的语句不在 try 块中,或者包含该语句的 try 块没有匹配的 catch 块,CLR 运行时将检查调用方法中是否有合适 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();
}
finally
{
//记住哦,如果你忘记 close,将会引发 IO 异常!
//if (fs != null)
//{
// fs.Close();
//}
} try
{
fs = fi.OpenWrite();
fs.WriteByte();
Console.WriteLine("OK!");
}
catch (IOException e)
{
Console.WriteLine("Fail!");
} Console.Read();
}

“Fail!”,这是因为上面注释了需要关闭文件流的语句,你可以尝试下去掉注释看看结果,记住哦,IO 操作都应该在结束时释放资源。
如果 WriteByte(0)(第9行) 引发了异常,那么在没有调用 fs.Close() 的情况下,你在第二个 try 块中尝试重新 OpenWrit() 的代码就会失败,因为此时文件会保持锁定状态。 假如你取消注释,由于会执行 finally 块(即使已引发异常),使得可以正确地关闭文件,从而避免再次引发异常。
如果在引发异常之后没有在调用堆栈上找到相匹配的 catch 块,则:
如果异常出现在析构函数中,则中止该析构函数并调用基类的析构函数(如果有)。
如果调用堆栈包含静态构造函数或静态字段初始值设定项,则会引发 TypeInitializationException,并将原始异常分配给新异常的 InnerException 属性。
如果到达线程的开头,将会终止线程。
C# 基础回顾系列
《C# 知识回顾 - 委托 delegate》、《C# 知识回顾 - 委托 delegate (续)》
《C# 知识回顾 - 事件入门》、《C# 知识回顾 - Event 事件》
《string 与 String,大 S 与小 S 之间没有什么不可言说的秘密》
【博主】反骨仔
【出处】http://www.cnblogs.com/liqingwen/p/6193534.html
【参考】https://docs.microsoft.com/zh-cn/dotnet/articles/csharp/programming-guide/exceptions/using-exceptions
【参考】微软官方文档
[C#] C# 知识回顾 - 学会使用异常的更多相关文章
- [C#] C# 知识回顾 - 学会处理异常
学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- [C#] C# 知识回顾 - 异常介绍
异常介绍 我们平时在写程序时,无意中(或技术不够),而导致程序运行时出现意外(或异常),对于这个问题, C# 有专门的异常处理程序. 异常处理所涉及到的关键字有 try.catch 和 finally ...
- [C#] C# 知识回顾 - 序列化
C# 知识回顾 - 序列化 [博主]反骨仔 [原文地址]http://www.cnblogs.com/liqingwen/p/5902005.html 目录 序列化的含义 通过序列化保存对象数据 众 ...
- java基础知识回顾之---java String final类普通方法
辞职了,最近一段时间在找工作,把在大二的时候学习java基础知识回顾下,拿出来跟大家分享,如果有问题,欢迎大家的指正. /* * 按照面向对象的思想对字符串进行功能分类. * ...
- C# 知识回顾 - 装箱与拆箱
装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 生活中的装箱与拆箱 我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃> ...
- Java基础知识回顾之七 ----- 总结篇
前言 在之前Java基础知识回顾中,我们回顾了基础数据类型.修饰符和String.三大特性.集合.多线程和IO.本篇文章则对之前学过的知识进行总结.除了简单的复习之外,还会增加一些相应的理解. 基础数 ...
- [C#] C# 知识回顾 - 装箱与拆箱
装箱与拆箱 目录 生活中的装箱与拆箱 C# 的装箱与拆箱 值类型和引用类型 装箱 拆箱 读者见解 生活中的装箱与拆箱 我们习惯了在网上购物,这次你想买本编程书 -- <C 语言从入门到放弃 ...
- [C#] C# 知识回顾 - Lambda
C# 知识回顾 - Lambda 序 它是第十一个希腊字母,一个拥有失意.无奈.孤独.低调等含义的流行符号,也指示一款称为“半条命”的游戏. 不过,这次我所讲的是 C# 中的 Lambda. 目录 L ...
随机推荐
- 你必须知道的EF知识和经验
注意:以下内容如果没有特别申明,默认使用的EF6.0版本,code first模式. 推荐MiniProfiler插件 工欲善其事,必先利其器. 我们使用EF和在很大程度提高了开发速度,不过随之带来的 ...
- [APUE]文件和目录(下)
一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...
- 卡片抽奖插件 CardShow
这个小项目(卡片秀)是一个卡片抽奖特效插件,用开源项目这样的词语让我多少有些羞愧,毕竟作为一个涉世未深的小伙子,用项目的标准衡量还有很大差距.不过该案例采用 jQuery 插件方式编写,提供配置参数并 ...
- iOS审核这些坑,腾讯游戏也踩过
作者:Jamie,专项技术测试工程师,在iOS预审和ASO优化领域从事专项测试相关工作,为腾讯游戏近100个产品提供专项服务. WeTest 导读 在App上架苹果应用商店的过程中,相信大多数iOS开 ...
- C#中如何创建PDF网格并插入图片
这篇文章我将向大家演示如何以编程的方式在PDF文档中创建一个网格,并将图片插入特定的网格中. 网上有一些类似的解决方法,在这里我选择了一个免费版的PDF组件.安装控件后,创建新项目,添加安装目录下的d ...
- SDWebImage源码解读之SDWebImageCache(下)
第六篇 前言 我们在SDWebImageCache(上)中了解了这个缓存类大概的功能是什么?那么接下来就要看看这些功能是如何实现的? 再次强调,不管是图片的缓存还是其他各种不同形式的缓存,在原理上都极 ...
- 防线修建 bzoj 2300
防线修建(1s 512MB)defense [问题描述] 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还 ...
- iOS app内存分析套路
iOS app内存分析套路 Xcode下查看app内存使用情况有2中方法: Navigator导航栏中的Debug navigator中的Memory Instruments 一.Debug navi ...
- 跨域问题,前端主动向后台发送cookie
跨域是什么? 从一个域名的网页访问另一个域名的资源,就会出现跨域.只要协议.端口.域名有一个不同就会出现跨域 例如: 1.协议不同 http://www.baidu.com:80 和 https:/ ...
- NodeJs 开发微信公众号(四)微信网页授权
微信的网页授权指的是在微信公众号中访问第三方网页时获取用户地理.个人等信息的权限.对于开发了自己的网页app应用时,获取个人的信息非常重要.上篇博客讲到了注册时可以获取用户的信息,很多人会问为什么还需 ...