C# 异常处理(一)
问题一:try-catch-finally 中有return的情况,会如何执行
很多人都会纠结这么一个问题try-catch-finally中有return的情况,我自己总结如下:
1.1 如果是值类型的话
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 含有return的测试 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 int j = Test(); 13 Console.WriteLine(j); 14 15 } 16 /// <summary> 17 /// 这个是测试return里面的是值类型就不会对他们有影响呢 18 /// </summary> 19 /// <returns></returns> 20 static int Test() 21 { 22 int i = 0; 23 24 try 25 { 26 27 return i; //为什么这里要加个return呢 28 } 29 catch (Exception) 30 { 31 32 i++; 33 return i; 34 35 } 36 finally 37 { 38 i = i + 2; 39 } 40 41 } 42 43 44 } 45 }
通过上面的代码可以看出,这里的finally执行了之后,对return返回没有影响 return返回结果还是0;
1.2 返回值是引用类型
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 引用类型测试 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 List<string> strList = Test(); 13 foreach (var i in strList) 14 { 15 Console.WriteLine(i); 16 } 17 Console.ReadKey(); 18 } 19 private static List<string> Test() 20 { 21 List<string> strList = new List<string>(); 22 strList.Add("aa"); 23 strList.Add("bb"); 24 strList.Add("cc"); 25 try 26 { 27 //这里没有发生异常的 28 strList.Add("trytry"); 29 return strList; 30 } 31 catch (Exception ex) 32 { 33 strList.Add("zzz"); 34 return strList; 35 } 36 finally 37 { 38 strList.Add("yyy"); 39 } 40 } 41 42 } 43 }
输出结果如下:
通过以上两个例子可以总结: 如果是值类型的话,finally里面的改变不会对try或者catch中的return返回值造成影响。
如果是引用类型的话,finally里面的改变会对try或者catch中的return返回值造成影响(除了String外)。
造成这个结果的主要原因就是return返回的是栈中的地址。
问题二:多个Try catch finally的执行顺序。
try这个执行顺序不说了。
catch块:如果Try块中的代码没有抛出异常的话呢,CLR永远都不会执行它的任何Catch块
如果是不会报异常的话,线程就会跳过catch块,直接执行finally块(如果有的话)。
但是如果try块里面报了异常的话呢。并且Catch也能捕捉到这个异常(第一层Catch就可以捕捉到)。那就是try catch finally的顺序执行。
假设第一层Catch没有匹配到,就会继续往上面的抛,直到Catch可以匹配到。如果没有匹配到Catch就直接报异常了,程序崩了(如果没有捕捉到异常的话呢,finally的语句是不会执行的。如果有finally的话,最后面会去执行finally)。
如果catch第一层没有捕捉到,在第二层也没有捕捉到,在第三层的Catch里面捕捉到这个异常的话呢,会在进入catch之前先之前第一层的finally(如果有),第二层finally执行完了,才去第三层执行对应的catch里面的内容:如下面代码所示:
static void MethodFour(){try{throw new NotImplementedException();}catch(DivideByZeroException ex){}finally{Console.WriteLine("最里面的 finally");}}
上面这个方法是不会匹配到异常,异常会往上面抛(它的调用如下)
try{MethodFour();//这里输出的顺序是先finally,再Exception。 }catch(Exception ex){//异常会往上抛,在它匹配到这个异常的时候.Console.WriteLine($"Exception");}finally{Console.WriteLine("最外面的 Finally");}
具体结果如何,大家可以动手试试。
问题三:很多人说Catch要指定先具体的异常类型,最后再写一个Exception。
try块:一般是可能报异常的。每一个try至少有一个catch块或finally块。
catch块:包含的是响应异常需要执行的代码。如果一个try块里面没有造成异常,CLR永远不会执行它的任何catch块。线程将跳过所有catch块,直接执行finally块(如果有的话)。
catch关键字后的圆括号中的表达式称为捕捉类型。C#要求捕捉类型必须是System.Exception或者它的派生类型。
有了这两个基础之后,再解释问题一,CLR是自上而下搜索匹配catch块,所以应该将较具体的异常放在顶部。也就是说首先要出现的是派生度最大的异常类型,接着是它们的基类型(如果有的话),最后是System.Exception(或者是没有指定任何捕捉类型的catch块)。
那么问题又来了,很多时候,我们是直接一个try{ ...}catch(excepiton ex){ ... } ,和我们上面说的做法(写到具体的异常类型)有多大区别呢。
直接上例子:
static void MethodOne(){try{int i = 0;int j = 10 / i;}catch(FormatException ex){//假设这里多一层比较,再匹配到 }catch (DuplicateWaitObjectException ex){//再多一层比较 }catch(DivideByZeroException ex){// Console.WriteLine("DivideByZeroException异常"); }catch(Exception ex){Console.WriteLine("Exception ONE");}}
static void MethodTwo(){try{int i = 0;int j = 10 / i;}catch (Exception ex){// Console.WriteLine("Exception TWO"); }}
上面的例子,跑出来的结果说明(大家动手跑一下),methodone(匹配到具体异常的)要比methondtwo(直接exception)要高效。
问题四:Throw和Throw ex区别
每次看到别人写的代码有时候Throw; 有时候又Throw ex;总是充满好奇,他们为什么要这么写,这样写有啥区别呢。下面我们一起来看看究竟。
1、先说Throw ex会重置异常,异常堆栈信息会重新抛出,这样就会影响我们根据异常信息来定位问题。
2、Throw 会传递异常,不会重置异常。
static void TestMethod(){try{Console.WriteLine($"ThreadId{Thread.CurrentThread.ManagedThreadId}");TestThrow();}catch (Exception ex){Console.WriteLine("除以零报异常了");//throw ex;//把异常信息向上抛了。throw ex;}}static void TestThrow(){var t = 0;var res = 10 / t;}
问题五:对于try catch finally对性能影响一说
//当异常被重置的话呢。try{}catch(FormatException ex){//这里写一个日志。logHelp.write(ex)throw new Exception("格式化异常");}catch(DivideByZeroException ex){//这里写一个日志。logHelp.write(ex)throw new Exception("尝试除以零");}catch(IndexOutOfRangeException ex){//这里写一个日志。logHelp.write(ex)throw new Exception("索引溢出");}catch(Exception ex){//这里写一个日志。logHelp.write(ex)throw new Exception("其他异常");}finally{//资源清理}
从上面这段代码,可以看到try catch finally给我们的感觉就是代码结构清晰,分门别类。
异常的处理好处有如下(个人觉得)
1、代码可读性很好,正常的逻辑和异常处理,资源清理都分开。
2、系统可靠性提升了。
3、链式调用方法可以很轻松的实现了。
关于性能这一说法:
一旦异常被抛出去的话,函数也会跟着return,而程序在执行时候,需要处理函数栈的上下文,如果函数栈比较深的话,性能就更加受影响了。从另外一方面来说,如果你的程序报异常了,就应该要停止执行了。程序本来就应该在没有异常的情况下执行的(所以你大部分情况下,程序是不会抛出异常的,对性能的影响也就不那么大了)。
转载于:https://www.cnblogs.com/gdouzz/p/4763224.html
C# 异常处理(一)相关推荐
- Go语言的错误异常处理机制及其应用
一.背景 在日常编写golang程序或阅读别人的golang代码时,我们总会看到如下的一堆代码块: xx, err = func(xx) if err != nil {//do sth. to tac ...
- SpringBoot (二) :全局异常处理设置
说在前面 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有 ...
- 2021年大数据常用语言Scala(三十四):scala高级用法 异常处理
目录 异常处理 捕获异常 抛出异常 异常处理 Scala中 无需在方法上声明异常 来看看下面一段代码. def main(args: Array[String]): Unit = {val i = 1 ...
- Java基础(七)--Exception异常处理
发现错误的理想时机是程序运行之前(编译期),然后不太现实,很多异常无法被发现(特别是业务上的数据),需要在运行时解决. 错误恢复机制保证代码健壮性的方式,异常处理在程序中很常见,也是必须的,必须考虑有 ...
- 零基础学习python_异常处理(32-33课)
我们写完python执行的时候是不是经常会遇到报错,而且报错都是大片红字,这样给别人的感受就是你写的程序怎么老是出问题啊,这样我们还咋么混下去呢?于是乎,就有了异常处理的东东. python的try语 ...
- Spring Security 实战干货:自定义异常处理
Spring Security 实战干货:自定义异常处理 转自:https://www.cnblogs.com/felordcn/p/12142514.html 文章目录 1. 前言 2. Sprin ...
- C++ 笔记(20)— 异常处理(抛出异常、捕获异常)
异常提供了一种转移程序控制权的方式. C++ 异常处理涉及到三个关键字: try . catch . throw . throw : 当问题出现时,程序会抛出一个异常.这是通过使用 throw 关键字 ...
- recover 没有捕获异常_GO语言异常处理机制panic和recover分析
本文实例分析了GO语言异常处理机制panic和recover.分享给大家供大家参考.具体如下: Golang 有2个内置的函数 panic() 和 recover(),用以报告和捕获运行时发生的程序错 ...
- ssm 异常捕获 统一处理_SSM 统一异常处理
SSM 统一异常处理 spring创建中, 处理异常可以使用try-cache处理, 也可以使用spring提供的统一异常处理 在spring中, 统一处理异常有2中方式 注解方式 @Exceptio ...
- java 异常的分类并举例_Java异常处理中的一些特殊情况举例
只使用try和finally不使用catch的原因和场景JDK并发工具包中,很多异常处理都使用了如下的结构,如AbstractExecutorService,即只有try和finally没有catch ...
最新文章
- RDKit | 基于SMILES查找化合物的MACCS密钥
- 转载:VMware虚拟机时钟不准的问题(linux图形界面投影到windows配置参考)--略有修改...
- 机器学习的数学基础(1)--Dirichlet分布
- JavaScript 复习之 事件模型 和 Event对象
- [Bugku][Web][CTF] 30-33 write up
- 六安瓜片在51CTO【礼树迎蛇 红满社区】
- Build desktop apps for Windows PCs
- 计算机系给未来的自己写信,写信给未来的自己
- python手机版-手机版python
- MapReduce 规划 系列十 采用HashPartitioner调整Reducer计算负荷
- laravel 下载使用
- 速卖通AE平台+聚石塔+奇门 完整教程V2
- 地震点、火点和气候数据收集
- 单片机2017福建省中职省赛_2017年福建省职业院校技能大赛首批设115个赛项
- 关于.net的一则笑话(无奈一笑)
- Windows系统win10系统流程图软件推荐
- socket函数接口
- 内嵌式js微信扫码登录及自定义样式
- PCB这个工艺,免费了!
- Python 入门指南第三节 | Python 简介
热门文章
- Linux下搭建DHCP服务器 【2020.12.01】
- anaconda 清华源挂了 怎么办 上交源ok
- Python爬取千条相亲数据,看看单身率90%的中国男女都在挑剔什么
- 最全数据指标体系集合!覆盖9个行业4个业务场景,全是干货
- 谁说数据分析很难?看完这7大分析套路后,还学不会的来找我
- 什么是数据、元数据、主数据?这可能是大多数人没看过的解释
- 利用BI搭建零售业数据信息平台
- jsf ajax循环调用,每次JSF ajax回发后执行JavaScript
- vscode 乱码_如何使用VS Code 编辑Keil项目(51/STM32)
- flowable activiti 回退 驳回_驳回复审中图文组合商标与图形商标不近似性如何论述?...