学会使用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();
 }

学会使用C#异常

如果引发异常的语句不在 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();
 }

学会使用C#异常

“Fail!”,这是因为上面注释了需要关闭文件流的语句,你可以尝试下去掉注释看看结果,记住哦,IO 操作都应该在结束时释放资源。

如果 WriteByte(0)(第9行) 引发了异常,那么在没有调用 fs.Close() 的情况下,你在第二个 try 块中尝试重新 OpenWrit() 的代码就会失败,因为此时文件会保持锁定状态。 假如你取消注释,由于会执行 finally 块(即使已引发异常),使得可以正确地关闭文件,从而避免再次引发异常。

如果在引发异常之后没有在调用堆栈上找到相匹配的 catch 块,则会可能会出现下面的情况:

  • 如果异常出现在析构函数中,则中止该析构函数并调用基类的析构函数(如果有)。

  • 如果调用堆栈包含静态构造函数或静态字段初始值设定项,则会引发 TypeInitializationException,并将原始异常分配给新异常的 InnerException 属性。

  • 如果到达线程的开头,将会终止线程。

来源:http://www.cnblogs.com/liqingwen/p/6193534.html

标签:C#,异常
0
投稿

猜你喜欢

  • 10分钟学会VS NuGet包私有化部署

    2022-04-23 02:28:31
  • java代理模式(静态代理、动态代理、cglib代理)

    2022-11-22 16:12:49
  • Java字符串拼接详解

    2022-10-17 06:22:51
  • java.lang.UnsatisfiedLinkError: %1 不是有效的Win32应用程序错误解决

    2022-06-14 23:21:51
  • C#通过指针实现快速拷贝的方法

    2022-09-26 01:43:08
  • C语言中队列的结构和函数接口的使用示例

    2022-01-08 06:56:40
  • javax.persistence中@Column定义字段类型方式

    2021-12-03 21:21:44
  • Android 仿今日头条评论时键盘自动弹出的效果(推荐)

    2022-07-24 15:00:45
  • Spring BeanFactory和FactoryBean区别解析

    2023-09-18 15:38:28
  • Android多渠道打包神器ProductFlavor详解

    2021-06-11 19:48:22
  • C#私有构造函数使用示例

    2021-12-31 02:14:53
  • maven+阿里云创建国内镜像的中央仓库(亲测可用)

    2023-05-12 22:38:58
  • maven中下载jar包源码和javadoc的命令介绍

    2023-07-27 04:41:01
  • Unity3d实现Flappy Bird游戏

    2023-09-17 20:54:29
  • java 实现通过 post 方式提交json参数操作

    2022-08-29 05:00:16
  • Java中输入与输出的方法总结

    2021-06-07 22:02:15
  • Android双向选择控件DoubleSeekBar使用详解

    2022-02-13 10:05:29
  • Spring Data JPA 之 JpaRepository的使用

    2023-11-24 21:23:40
  • kotlin 定义接口并实现回调的例子

    2022-12-06 14:30:19
  • C++ 中的异常抛出和捕获方式

    2021-06-08 21:24:19
  • asp之家 软件编程 m.aspxhome.com