问题一: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# 异常处理(一)相关推荐

  1. Go语言的错误异常处理机制及其应用

    一.背景 在日常编写golang程序或阅读别人的golang代码时,我们总会看到如下的一堆代码块: xx, err = func(xx) if err != nil {//do sth. to tac ...

  2. SpringBoot (二) :全局异常处理设置

    说在前面 在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler.@InitBinder.@ModelAttribute,并应用到所有 ...

  3. 2021年大数据常用语言Scala(三十四):scala高级用法 异常处理

    目录 异常处理 捕获异常 抛出异常 异常处理 Scala中 无需在方法上声明异常 来看看下面一段代码. def main(args: Array[String]): Unit = {val i = 1 ...

  4. Java基础(七)--Exception异常处理

    发现错误的理想时机是程序运行之前(编译期),然后不太现实,很多异常无法被发现(特别是业务上的数据),需要在运行时解决. 错误恢复机制保证代码健壮性的方式,异常处理在程序中很常见,也是必须的,必须考虑有 ...

  5. 零基础学习python_异常处理(32-33课)

    我们写完python执行的时候是不是经常会遇到报错,而且报错都是大片红字,这样给别人的感受就是你写的程序怎么老是出问题啊,这样我们还咋么混下去呢?于是乎,就有了异常处理的东东. python的try语 ...

  6. Spring Security 实战干货:自定义异常处理

    Spring Security 实战干货:自定义异常处理 转自:https://www.cnblogs.com/felordcn/p/12142514.html 文章目录 1. 前言 2. Sprin ...

  7. C++ 笔记(20)— 异常处理(抛出异常、捕获异常)

    异常提供了一种转移程序控制权的方式. C++ 异常处理涉及到三个关键字: try . catch . throw . throw : 当问题出现时,程序会抛出一个异常.这是通过使用 throw 关键字 ...

  8. recover 没有捕获异常_GO语言异常处理机制panic和recover分析

    本文实例分析了GO语言异常处理机制panic和recover.分享给大家供大家参考.具体如下: Golang 有2个内置的函数 panic() 和 recover(),用以报告和捕获运行时发生的程序错 ...

  9. ssm 异常捕获 统一处理_SSM 统一异常处理

    SSM 统一异常处理 spring创建中, 处理异常可以使用try-cache处理, 也可以使用spring提供的统一异常处理 在spring中, 统一处理异常有2中方式 注解方式 @Exceptio ...

  10. java 异常的分类并举例_Java异常处理中的一些特殊情况举例

    只使用try和finally不使用catch的原因和场景JDK并发工具包中,很多异常处理都使用了如下的结构,如AbstractExecutorService,即只有try和finally没有catch ...

最新文章

  1. RDKit | 基于SMILES查找化合物的MACCS密钥
  2. 转载:VMware虚拟机时钟不准的问题(linux图形界面投影到windows配置参考)--略有修改...
  3. 机器学习的数学基础(1)--Dirichlet分布
  4. JavaScript 复习之 事件模型 和 Event对象
  5. [Bugku][Web][CTF] 30-33 write up
  6. 六安瓜片在51CTO【礼树迎蛇 红满社区】
  7. Build desktop apps for Windows PCs
  8. 计算机系给未来的自己写信,写信给未来的自己
  9. python手机版-手机版python
  10. MapReduce 规划 系列十 采用HashPartitioner调整Reducer计算负荷
  11. laravel 下载使用
  12. 速卖通AE平台+聚石塔+奇门 完整教程V2
  13. 地震点、火点和气候数据收集
  14. 单片机2017福建省中职省赛_2017年福建省职业院校技能大赛首批设115个赛项
  15. 关于.net的一则笑话(无奈一笑)
  16. Windows系统win10系统流程图软件推荐
  17. socket函数接口
  18. 内嵌式js微信扫码登录及自定义样式
  19. PCB这个工艺,免费了!
  20. Python 入门指南第三节 | Python 简介

热门文章

  1. Linux下搭建DHCP服务器 【2020.12.01】
  2. anaconda 清华源挂了 怎么办 上交源ok
  3. Python爬取千条相亲数据,看看单身率90%的中国男女都在挑剔什么
  4. 最全数据指标体系集合!覆盖9个行业4个业务场景,全是干货
  5. 谁说数据分析很难?看完这7大分析套路后,还学不会的来找我
  6. 什么是数据、元数据、主数据?这可能是大多数人没看过的解释
  7. 利用BI搭建零售业数据信息平台
  8. jsf ajax循环调用,每次JSF ajax回发后执行JavaScript
  9. vscode 乱码_如何使用VS Code 编辑Keil项目(51/STM32)
  10. flowable activiti 回退 驳回_驳回复审中图文组合商标与图形商标不近似性如何论述?...