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; } }
可以看到Form1_Click、Form1_Load、Form1_Enter中的try catch已經被編譯器優化掉了:
lick中的try catch中對try catch進行了處理:
.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
==》可以看出三種try catch的寫法對於release版本的程式碼來說是完全一樣,也不會產生任何的效能消耗:
IL_0000: ret //即为 return 标记 返回值
)。
那麼對debug模式下的IL代碼是什麼樣子的呢?
.locals init ([0] class [mscorlib]System.Exception ee) //定义 Exception 类型参数 ee (此时已经把ee存入了Call Stack中)
可以看出四種寫法在debug模式下差異只是:rethrow與throw的差異。 IL中rethrow與throw分別代表啥呢?
Throw:引發目前位於計算堆疊上的異常物件。 Rethrow:再次引發目前異常。
當我們拋出一個異常時, CLR會重新設定一個異常起始點。 CLR只記錄最近一次異常拋出的位置。下面程式碼拋出異常,導致CLR重新設定該異常的起始點: try
{
}
catch
{
throw;
}
try
{
}
catch (Exception)
{
throw;
}
try
{
}
catch (Exception ee)
{
throw;
}
相反,如果我們拋出一個物件異常物件,起始點將不會重新設定,下面程式碼拋出一個異常,但不會導致CLR重新設定異常的起始點:
.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
C#中使用throw和異常的區別。
在C#中推薦使用throw;來拋出異常;throw ex;會將到現在為止的所有資訊清空,認為你catch到的異常已經被處理了,只不過處理過程中又被清空新的異常,從而找不到真正的錯誤來源。
throw e重新拋出異常,並非轉發原來的異常,而會更改包括StackTrace在內的許多異常內部信息;對於調用連很深情況,性能損耗超出想像。
以上就是C# 異常處理(Catch Throw)IL分析的內容,更多相關內容請關注PHP中文網(www.php.cn)!