您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

C# 异常处理(Catch Throw)IL分析

2024/6/19 23:29:41发布25次查看
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到的异常已经被处理了,只不过处理过程中又抛出新的异常,从而找不到真正的错误源。
throw e重新抛出异常,并非转发原来的异常,而会更改包括stacktrace在内的许多异常内部信息;对于调用连很深情况,性能损耗超出想象。
以上就是c# 异常处理(catch  throw)il分析的内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product