天天看點

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

來自部落格

<a href="http://blog.csdn.net/vipxiaotian/article/details/1524059" target="_blank">http://blog.csdn.net/vipxiaotian/article/details/1524059</a>

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

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 &gt;

leave.s target

退出受保護的代碼區域(短格式)。

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

leave.s 指令無條件将控制轉移到傳遞的目标指令,這表示為距目前指令之後的指令的開始處的 1 位元組有符号偏移量。

leave.s 指令類似于 br 指令,但它可用于退出 try、filter 或 catch 塊,而一般分支指令隻能在此類塊中使用以在其内部轉移控制。leave.s 指令清空計算堆棧并確定執行周圍适當的 finally 塊。

不能使用 leave.s 指令退出 finally 塊。為了簡化異常處理程式的代碼生成,一個有效的方法是在 Catch 塊的内部使用 leave.s 指令将控制轉移到關聯的 try 塊中的任何指令。

如果指令有一個或多個字首代碼,則隻能将控制轉移到其中的第一個字首。

      OK,至此,一切明了了<b>~~leave.s會確定finally塊的執行,是以,即使在catch中使用了return語句想直接跳出,還是會先執行finally再return的</b>