C#:在catch中return,會執行finally嗎?

本文轉自 vipxiaotian(CSDN)函數

請參考下面一段簡單的語句塊:spa

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:  }.net

       你們有沒有想過執行到第七步以後會出現什麼結果?line7是一條return語句,按道理來講return語句的做用就是跳出當前函數並繼續調用地址的下一條語句,那麼說就不執行finally,可是我想你們應該都記得finally的做用:確保有無異常的狀況下finally塊中的語句都能執行……因而,矛盾就這樣產生鳥。。。ip

      在繼續下去看答案以前,親愛的讀者們,大家以爲會是什麼結果呢?finally會不會執行呢?請先思考一下再看答案。ci

       既然在程序層看不出貓膩,那麼咱們不妨深刻IL層去挖掘一下,上面代碼的IL是這樣子地:get

  .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:  retstring

      請注意上面上面黃色部分代碼,在catch塊中,使用了leave.s這條命令來跳轉到IL_0019這一行,而0019這一行正是ret命令,看起來……應該不會執行到finally纔對~~難道說,從catch塊就直接跳出了?!it

      我想該是時候去弄明白leave.s這條命令的做用了,看看Microsoft給出的定義:io

格式 彙編格式 說明
DE < int8 > leave.s target 退出受保護的代碼區域(短格式)。

沒有爲此指令指定任何堆棧轉換行爲。table

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的

相關文章
相關標籤/搜索