博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C# 异常处理(Catch Throw)IL分析
阅读量:5965 次
发布时间:2019-06-19

本文共 5603 字,大约阅读时间需要 18 分钟。

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在内的许多异常内部信息;对于调用连很深情况,性能损耗超出想象。

拓展阅读:

你可能感兴趣的文章
zepto返回顶部动画
查看>>
CVBS视频信号解析
查看>>
必要时进行保护性拷贝
查看>>
Codeforces Round #356 (Div. 1) D. Bear and Chase 暴力
查看>>
甲骨文Java Archive
查看>>
查看数据库错误日志的位置
查看>>
电信网络拓扑图自动布局
查看>>
C#中List〈string〉和string[]数组之间的相互转换
查看>>
洛谷P1108 低价购买[DP | LIS方案数]
查看>>
通达信里的统计函数及区块背景函数
查看>>
redis主从配置<转>
查看>>
8 行 Node.js 代码实现代理服务器
查看>>
水印,图片验证码
查看>>
C#编程(七十六)----------使用指针实现基于栈的高性能数组
查看>>
PostgreSql 分页limit
查看>>
在MySQL中创建cm-hive使用的数据库及账号
查看>>
HDU 2503 a/b + c/d(最大公约数与最小公倍数,板子题)
查看>>
python总结
查看>>
hdu 5215 Cycle
查看>>
GCD学习(五) dispatch_barrier_async
查看>>