• 【Emit基础】在IL中进行异常处理


         本文通过一个简单的示例来说明在IL中进行异常处理时要注意的关键点。

         我们来看一个包含try...catch...finally的示例:

            public void TestEF()
            {          
                TransactionScopeFactory factory 
    = new TransactionScopeFactory(null);
                TransactionScope scope 
    = factory.NewTransactionScope(false);

                
    try
                {                
                    scope.Commit();
                }
                
    catch (Exception ee)
                {
                    
    string msg = ee.Message;
                }
                
    finally
                {
                    scope.Dispose();
                }
            }

         这段代码实际上与使用using是等价的:

    public void TestEF()
    {
        TransactionScopeFactory factory 
    = new TransactionScopeFactory(null);
        
    using (TransactionScope scope = factory.NewTransactionScope(false))
        {
            
    try
            {
                scope.Commit();
            }
            
    catch (Exception ee)
            {
                
    string msg = ee.Message;
            }
        }
    }

         它们对应的IL代码如下所示:

    .method public hidebysig instance void TestEF() cil managed
    {
        .maxstack 
    2
        .locals init (
            [
    0class [DataRabbit.Application]DataRabbit.Application.TransactionScopeFactory factory,
            [
    1class [DataRabbit.Application]DataRabbit.Application.TransactionScope scope,
            [
    2class [mscorlib]System.Exception ee,
            [
    3string msg)
        L_0000: nop 
        L_0001: ldnull 
        L_0002: newobj instance 
    void [DataRabbit.Application]DataRabbit.Application.TransactionScopeFactory::.ctor(class [DataRabbit]DataRabbit.DataConfiguration)
        L_0007: stloc.
    0 
        L_0008: ldloc.
    0 
        L_0009: ldc.i4.
    0 
        L_000a: callvirt instance 
    class [DataRabbit.Application]DataRabbit.Application.TransactionScope [DataRabbit.Application]DataRabbit.Application.TransactionScopeFactory::NewTransactionScope(bool)
        L_000f: stloc.
    1 
        L_0010: nop 
        L_0011: ldloc.
    1 
        L_0012: callvirt instance 
    void [DataRabbit.Application]DataRabbit.Application.TransactionScope::Commit()
        L_0017: nop 
        L_0018: nop 
        L_0019: leave.s L_0027
        L_001b: stloc.
    2 
        L_001c: nop 
        L_001d: ldloc.
    2 
        L_001e: callvirt instance 
    string [mscorlib]System.Exception::get_Message()
        L_0023: stloc.
    3 
        L_0024: nop 
        L_0025: leave.s L_0027
        L_0027: nop 
        L_0028: leave.s L_0034
        L_002a: nop 
        L_002b: ldloc.
    1 
        L_002c: callvirt instance 
    void [DataRabbit.Application]DataRabbit.Application.TransactionScope::Dispose()
        L_0031: nop 
        L_0032: nop 
        L_0033: endfinally 
        L_0034: nop 
        L_0035: ret 
        .
    try L_0010 to L_001b catch [mscorlib]System.Exception handler L_001b to L_0027
        .
    try L_0010 to L_002a finally handler L_002a to L_0034
    }

         我们来剖析这段IL中的异常处理流程:

    1.有最后的两句代码,我们看到:

    (1)try...catch...finally 是由try...catch 和 try...finally两部分构成。

    (2)try...finally 中的try块内含了catch块。

    即类似这样:

               .try
                  
    {
                      .
    try
                      {
                      }
                      
    catch
                      {
                      }
                  }
                  
    finally
                  {
                  }

    2.try块、catch块(catch handler)只能通过leave(或leave.s)退出。

    3.finally块(finally handler)必须通过endfinally退出。

    4.由于try...catch 和 try...finally两部分都需要退出try块,所以我们看到在L_0019 和 L_0028 处都有对应的leave.s指令。

    5.程序中如果没有finally块,则IL中只需要处理try...catch 部分;同理,如果程序中没有catch块,则IL只需要处理try...finally部分。

    6.总结起来,IL的异常处理类似这个样子:

               .try
                  
    {
                      .
    try
                      {

                             leave L1
                      }
                      
    catch
                      {

                             leave L1
                      }

                      leave L2

                  }
                  
    finally
                  {

                        endfinally
                  }

  • 相关阅读:
    第一部分 题目要求
    完全卸载oracle
    zabbix的面试题目总结
    性能优化之MySQL调优篇
    select与epoll、apache与nginx实现原理对比
    深度优化LNMP之PHP
    深度优化LNMP之Nginx (转)
    git常用命令
    ansible 安装与卸载软件
    java8两个List集合取交集、并集、差集、去重并集
  • 原文地址:https://www.cnblogs.com/zhuweisky/p/1295923.html
Copyright © 2020-2023  润新知