【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 (
        [0] class [DataRabbit.Application]DataRabbit.Application.TransactionScopeFactory factory,
        [1] class [DataRabbit.Application]DataRabbit.Application.TransactionScope scope,
        [2] class [mscorlib]System.Exception ee,
        [3] string 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
              }

 

 

 

 

时间: 2024-08-01 03:49:45

【Emit基础】在IL中进行异常处理的相关文章

【Emit基础】IL中发布、订阅、触发事件

     在下面的例子中,我定义了一个事件发布类Computer,事件订阅者ComputerManager.Computer发布了一个OnAction事件,并且该事件在Increase方法被调用时触发.ComputerManager接收到事件通知时,会将成员字段handleCount增加1.      先看Computer的定义: .namespace ILTest {     .class public auto ansi beforefieldinit Computer extends [m

【Emit基础】IL定义方法的语法详解

     在IL中,方法的定义语法: .method <flags> <call_conv> <ret_type> <name>(<arg_list>) <impl> {   <method_body> } 一.Flags部分可设置 1.可访问性 privatescope: 该方法不能被引用. private: 该方法只能被自身及其嵌套类型调用. famandassem: 该方法只能被当前程序集内部的继承类型调用.(int

Symbian学习总结-基础篇-Symbian C++中的异常处理

在现代高级语言中,大多数语言都有对应处理异常的关键字,如:C++中的try/catch,Delphi中的Try/Except/Finally,这些关键字都被编译器直接的支持. 但是,当Symbian OS C++被发明的时候,C++中的关键字try/catch/finally还没有被标准支持.而且照Symbian官方的话来说,C++的异常处理机制太笨重,不够轻量级,他们设计了一套效率更加高,更适合于小型的.内存受限的设备的异常处理机制. 一.回顾历史 在标准C++中,我们使用如下方法来处理异常:

浅析Lua编程中的异常处理

  这篇文章主要介绍了浅析Lua编程中的异常处理,是Lua入门学习中的基础知识,要的朋友可以参考下 需要进行错误处理 错误处理是必要的,因为真实世界中的操作通常需要使用复杂的操作,包括文件操作,数据库事务和web服务调用.没人关心错误的业务,涉及保密信息或金钱交易时造成大的损失. 在任何编程,总是有错误处理的要求.错误可以是两种类型,其中包括, 语法错误 运行时错误 语法错误 因使用不当造成的各种程序组件,如运算符和表达式中出现语法错误.一个简单的例子中的语法错误如下所示. 代码如下: a ==

Struts2中的异常处理

  因为在Action的execute方法声明时就抛出了Exception异常,所以我们无需再execute方法中捕捉异常,仅需在struts.xml 中配置异常处理. 为了使用Struts2的异常处理机制,必须打开Struts2的异常映射功能,这需要exception拦截器.在struts-default.xml文件中已经开启了exception拦截器. 声明式异常捕捉 Struts2的异常处理机制是通过在struts.xml文件中配置<exception-mapping--/>元素完成的,

JavaScript中的异常处理方法介绍

 这篇文章主要介绍了详解JavaScript中的异常处理方法,包括基本的try...catch语句和throw语句的使用,需要的朋友可以参考下     有三种类型的编程错误:(1)语法错误和(2)运行时错误(3)逻辑错误: 语法错误: 语法错误,也被称为解析错误,在编译时进行传统的编程语言,并出现在JavaScript解释时. 例如,下面一行将导致一个语法错误,因为它缺少一个右括号: ? 1 2 3 4 5 <script type="text/javascript"> &

JS中的异常处理方法分享

我们在编写js过程中,难免会遇到一些代码错误问题,需要找出来,有些时候怕因为js问题导致用户体验差,这里给出一些解决方法 js容错语句,就是js出错也不提示错误(防止浏览器右下角有个黄色的三角符号,要不用户体验不好)    代码如下: window.onerror=function(){return true;}        下面是为了获取js异常信息,方便开发者找回问题   1,try...catch...   代码如下: <script type="text/javascript&q

Python中的异常处理

  这篇文章主要介绍了解析Python中的异常处理,异常处理是学习每门编程语言都必须掌握的重要知识,本文代码基于Python2.x版本,需要的朋友可以参考下 在程序运行的过程中,如果发生了错误,可以事先约定返回一个错误代码,这样,就可以知道是否有错,以及出错的原因.在操作系统提供的调用中,返回错误码非常常见.比如打开文件的函数open(),成功时返回文件描述符(就是一个整数),出错时返回-1. 用错误码来表示是否出错十分不便,因为函数本身应该返回的正常结果和错误码混在一起,造成调用者必须用大量的

T-SQL编程中的异常处理-异常捕获(try catch)与抛出异常(throw)

原文:T-SQL编程中的异常处理-异常捕获(try catch)与抛出异常(throw)   本文出处: http://www.cnblogs.com/wy123/p/6743515.html     T-SQL编程与应用程序一样,都有异常处理机制,比如异常的捕获与异常的抛出(try catch throw),本文简单介绍异常捕获与异常抛出在T-SQL编程中的实际使用 . 异常处理简单说明 异常捕获在应用程序编程中非常常见,提供了处理程序运行时出现的任何意外或异常情况的方法刚毕业的时候对于异常处