C# 异常处理(Catch Throw)IL分析-阿里云开发者社区

开发者社区> jiankunking> 正文

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

简介: 1、catch throw的几种形式及性能影响: private void Form1_Click(object sender, EventArgs e) { try { } catch { throw;
+关注继续查看

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

拓展阅读:

IL指令详细

.NET中异常处理的最佳实践(译



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
来更快的Maven了,我的天,速度提升了8倍!(1)
更快的Maven来了,我的天,速度提升了8倍!(1)
56 0
“Haas物联网设备云端一体极客大赛”入选2021中国最受开发者欢迎技术活动
近日,开发者社区SegmentFault思否发布《2021 中国最受开发者欢迎的技术活动榜单》,依托社区活动板块及全站数百万开发者用户行为数据,活动规模、内容好评度、行业综合影响力指标,评选出 30 家场最受开发者欢迎的技术活动,Haas物联网设备云端一体极客大赛入选。
53 0
Taro3.x 快速开发微信小程序以及 minidebug 小程序调试工具使用
Taro3.x 快速开发微信小程序以及 minidebug 小程序调试工具使用
4 0
synchronized 中的 4 个优化,你知道几个?(2)
synchronized 中的 4 个优化,你知道几个?(2)
4 0
渐进符号 big-O、big-Ω、big-Θ
算法分析 渐进符号 big-O、big-Ω、big-Θ
25 0
@Autowired报错的4种解决方案和原因分析!(1)
@Autowired报错的4种解决方案和原因分析!(1)
11 0
零基础如何上手APICloud App、小程序多端开发
业务需求变化快、开发人员成本高是现在企业面临的主要问题。多端开发技术则可以很好的解决这些问题,开发一次可以生成iOS、Android、小程序、Web等多端应用。APICloud凭借多年的移动开发技术积累,为开发者提供了一套高性能的多端开发技术,可以高效的开发企业级应用程序。
47 0
02_Bootstrap起步2|学习笔记
快速学习 02_Bootstrap起步2
14 0
常量和变量_C语言简介|学习笔记
快速学习常量和变量_C语言简介
5 0
+关注
726
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载