• C#:在catch中return,会执行finally吗?


    本文转自 vipxiaotian(CSDN)

    请参考下面一段简单的语句块:

    1:  try
    2:  {
    3:      throw new Exception("new exception");
    4:  }
    5:  catch(Exception ex)
    6:  {
    7:      return;
    8:  }
    9:  finally
    10:  {
    11:      Console.WriteLine("a");
    12:  }

           大家有没有想过执行到第七步之后会出现什么结果?line7是一条return语句,按道理来说return语句的作用就是跳出当前函数并继续调用地址的下一条语句,那么说就不执行finally,但是我想大家应该都记得finally的作用:确保有无异常的情况下finally块中的语句都能执行……于是,矛盾就这样产生鸟。。。

          在继续下去看答案之前,亲爱的读者们,你们觉得会是什么结果呢?finally会不会执行呢?请先思考一下再看答案。

           既然在程序层看不出猫腻,那么我们不妨深入IL层去挖掘一下,上面代码的IL是这样子地:

      .try
      {
        .try
        {
          IL_0000:  ldstr      "new exception"
          IL_0005:  newobj     instance void [mscorlib]System.Exception::.ctor(string)
          IL_000a:  throw
        }  // end .try
        catch [mscorlib]System.Exception 
        {
          IL_000b:  stloc.0
          IL_000c:  leave.s    IL_0019
        }  // end handler
      }  // end .try
      finally
      {
        IL_000e:  ldstr      "a"
        IL_0013:  call       void [mscorlib]System.Console::WriteLine(string)
        IL_0018:  endfinally
      }  // end handler
      IL_0019:  ret

          请注意上面上面黄色部分代码,在catch块中,使用了leave.s这条命令来跳转到IL_0019这一行,而0019这一行正是ret命令,看起来……应该不会执行到finally才对~~难道说,从catch块就直接跳出了?!

          我想该是时候去弄明白leave.s这条命令的作用了,看看Microsoft给出的定义:

    格式汇编格式说明
    DE < int8 > leave.s target 退出受保护的代码区域(短格式)。

    没有为此指令指定任何堆栈转换行为。

    leave.s 指令无条件将控制转移到传递的目标指令,这表示为距当前指令之后的指令的开始处的 1 字节有符号偏移量。

    leave.s 指令类似于 br 指令,但它可用于退出 tryfilter 或 catch 块,而一般分支指令只能在此类块中使用以在其内部转移控制。leave.s 指令清空计算堆栈并确保执行周围适当的 finally 块。

    不能使用 leave.s 指令退出 finally 块。为了简化异常处理程序的代码生成,一个有效的方法是在 Catch 块的内部使用 leave.s 指令将控制转移到关联的 try 块中的任何指令。

    如果指令有一个或多个前缀代码,则只能将控制转移到其中的第一个前缀。

          OK,至此,一切明了了~~leave.s会确保finally块的执行,所以,即使在catch中使用了return语句想直接跳出,还是会先执行finally再return的

  • 相关阅读:
    数据类型
    java基础
    Codeforces Round #655 (Div. 2) B. Omkar and Last Class of Math(数论)
    Codeforces Round #655 (Div. 2) A. Omkar and Completion(构造)
    LibreOJ
    QT入门-QMainWindow类
    WCF 请求与响应参数大小设置
    Python 代码性能优化技巧
    lists,tuples and sets of Python
    SQL Language
  • 原文地址:https://www.cnblogs.com/harmonyboy/p/3403729.html
Copyright © 2020-2023  润新知