学会使用C#异常

发布时间 - 2026-01-10 22:03:30    点击率:

在 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 属性。
  • 如果到达线程的开头,将会终止线程。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!


# C#  # 异常  # C#解决SQlite并发异常问题的方法(使用读写锁)  # 详解C#编程中异常的创建和引发以及异常处理  # 浅谈C#中简单的异常引发与处理操作  # 解析C#中断言与异常的应用方式及异常处理的流程控制  # 轻松学习C#的异常处理  # C#中抛出异常用法实例  # C# WinForm捕获未处理的异常实例解析  # c#实现把异常写入日志示例(异常日志)  # C#异常处理详解  # 解析c#在未出现异常情况下查看当前调用堆栈的解决方法  # 就会  # 将会  # 自定义  # 则会  # 引发了  # 抛出  # 时将  # 小二  # 小三  # 这是  # 情况下  # 这一  # 如果你  # 在这里  # 放在  # 你可以  # 第一个  # 多个  # 句柄  # 出现在 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程  Laravel怎么在Blade中安全地输出原始HTML内容  如何在Windows服务器上快速搭建网站?  三星网站视频制作教程下载,三星w23网页如何全屏?  音乐网站服务器如何优化API响应速度?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验  Python文件流缓冲机制_IO性能解析【教程】  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  Laravel怎么配置.env环境变量_Laravel生产环境敏感数据保护与读取【方法】  Thinkphp 中 distinct 的用法解析  bing浏览器学术搜索入口_bing学术文献检索地址  如何用好域名打造高点击率的自主建站?  Microsoft Edge如何解决网页加载问题 Edge浏览器加载问题修复  canvas 画布在主流浏览器中的尺寸限制详细介绍  高防服务器租用如何选择配置与防御等级?  WordPress 子目录安装中正确处理脚本路径的完整指南  Android自定义listview布局实现上拉加载下拉刷新功能  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  Laravel中间件如何使用_Laravel自定义中间件实现权限控制  Laravel如何使用.env文件管理环境变量?(最佳实践)  香港服务器租用每月最低只需15元?  如何在阿里云域名上完成建站全流程?  使用spring连接及操作mongodb3.0实例  微信小程序 scroll-view组件实现列表页实例代码  Laravel怎么实现搜索高亮功能_Laravel结合Scout与Algolia全文检索【实战】  微信小程序 配置文件详细介绍  如何在建站宝盒中设置产品搜索功能?  JS去除重复并统计数量的实现方法  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  ,南京靠谱的征婚网站?  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  如何快速搭建虚拟主机网站?新手必看指南  Python文件异常处理策略_健壮性说明【指导】  北京企业网站设计制作公司,北京铁路集团官方网站?  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  如何快速重置建站主机并恢复默认配置?  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  MySQL查询结果复制到新表的方法(更新、插入)  高端网站建设与定制开发一站式解决方案 中企动力  黑客如何通过漏洞一步步攻陷网站服务器?  Laravel如何为API生成Swagger或OpenAPI文档  如何选择PHP开源工具快速搭建网站?  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  Laravel怎么判断请求类型_Laravel Request isMethod用法  如何在搬瓦工VPS快速搭建网站?  JavaScript如何实现错误处理_try...catch如何捕获异常?