程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C# 異常處理(Catch Throw)IL分析

C# 異常處理(Catch Throw)IL分析

編輯:C#入門知識

C# 異常處理(Catch Throw)IL分析


1、catch throw的幾種形式及性能影響:

 

 private void Form1_Click(object sender, EventArgs e)
        {
            try
            {

            }
            catch
            {
                throw;
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {

            }
            catch (Exception)
            {
                throw;
            }
        }
        private void Form1_Enter(object sender, EventArgs e)
        {
            try
            {

            }
            catch (Exception ee)
            {
                throw;
            }
        }
        private void Form1_DoubleClick(object sender, EventArgs e)
        {
            try
            {

            }
            catch (Exception ee)
            {
                throw ee;
            }
        }
對應的IL代碼(以下代碼是release版本的IL代碼):

 

.method private hidebysig instance void  Form1_Click(object sender,
                                                     class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method Form1::Form1_Click

.method private hidebysig instance void  Form1_Load(object sender,
                                                    class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method Form1::Form1_Load

.method private hidebysig instance void  Form1_Enter(object sender,
                                                     class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method Form1::Form1_Enter

.method private hidebysig instance void  Form1_DoubleClick(object sender,
                                                           class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       1 (0x1)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.Exception ee)
  IL_0000:  ret
} // end of method Form1::Form1_DoubleClick
可以看到Form1_Click、Form1_Load、Form1_Enter中的try catch已經被編譯器優化掉了:

 

 

IL_0000:  ret         //即為  return  標記 返回值

 

只有Form1_DoubleClick中的try catch中對try catch進行了處理:

 

 .locals init ([0] class [mscorlib]System.Exception ee) //定義 Exception 類型參數 ee (此時已經把ee存入了Call Stack中)
即在Form1_DoubleClick中的try catch才會對性能產生影響。

==》可以看出一下三種try catch的寫法對於release版本的代碼來說是完全一樣,也不會產生任何的性能消耗:

 

           try
            {

            }
            catch
            {
                throw;
            }
            try
            {

            }
            catch (Exception)
            {
                throw;
            }
            try
            {

            }
            catch (Exception ee)
            {
                throw;
            }
對於上面的結論大家可以寫測試demo驗證一下 ,本人驗證過偷笑

 

那麼對於debug模式下的IL代碼是什麼樣子的呢?

 

.method private hidebysig instance void  Form1_Click(object sender,
                                                     class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       11 (0xb)
  .maxstack  1
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  nop
    IL_0003:  leave.s    IL_0009
  }  // end .try
  catch [mscorlib]System.Object 
  {
    IL_0005:  pop
    IL_0006:  nop
    IL_0007:  rethrow
  }  // end handler
  IL_0009:  nop
  IL_000a:  ret
} // end of method Form1::Form1_Click

.method private hidebysig instance void  Form1_Load(object sender,
                                                    class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       11 (0xb)
  .maxstack  1
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  nop
    IL_0003:  leave.s    IL_0009
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0005:  pop
    IL_0006:  nop
    IL_0007:  rethrow
  }  // end handler
  IL_0009:  nop
  IL_000a:  ret
} // end of method Form1::Form1_Load

.method private hidebysig instance void  Form1_Enter(object sender,
                                                     class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       11 (0xb)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.Exception ee)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  nop
    IL_0003:  leave.s    IL_0009
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0005:  stloc.0
    IL_0006:  nop
    IL_0007:  rethrow
  }  // end handler
  IL_0009:  nop
  IL_000a:  ret
} // end of method Form1::Form1_Enter

.method private hidebysig instance void  Form1_DoubleClick(object sender,
                                                           class [mscorlib]System.EventArgs e) cil managed
{
  // 代碼大小       11 (0xb)
  .maxstack  1
  .locals init ([0] class [mscorlib]System.Exception ee)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  nop
    IL_0003:  leave.s    IL_0009
  }  // end .try
  catch [mscorlib]System.Exception 
  {
    IL_0005:  stloc.0
    IL_0006:  nop
    IL_0007:  ldloc.0
    IL_0008:  throw
  }  // end handler
  IL_0009:  nop
  IL_000a:  ret
} // end of method Form1::Form1_DoubleClick
可以看出四種寫法在debug模式下區別只是:rethrow與throw的區別。IL中rethrow與throw分別代表啥呢?

 

Throw:引發當前位於計算堆棧上的異常對象。
Rethrow:再次引發當前異常。

即當我們拋出一個異常時, CLR會重新設置一個異常起始點。 CLR只記錄最近一次異常拋出的位置。下面代碼拋出一個異常,從而導致CLR重新設置該異常的起始點:

 

            try
            {
                //一些處理
            }
            catch (Exception e)
            {
                //一些處理
                throw e;   //CLR認為這裡是異常的起始點
            }
相反,如果我們拋出一個異常對象, CLR將不會重新設置其堆棧的起始點,下面代碼拋出一個異常,但不會導致CLR重新設置異常的起始點:

 

           try
            {
                //一些處理
            }
            catch (Exception e)
            {
                //一些處理
                throw;  //CLR不會重新設置異常的起始點
            }
C#中使用throw和throw ex拋出異常,但二者是有區別的。

在C#中推薦使用throw;來拋出異常;throw ex;會將到現在為止的所有信息清空,認為你catch到的異常已經被處理了,只不過處理過程中又拋出新的異常,從而找不到真正的錯誤源。

拓展閱讀:

IL指令詳細

.NET中異常處理的最佳實踐(譯)

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved