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

本文通过一个具体的示例详细解析了在IL(Intermediate Language)中如何实现try...catch...finally异常处理结构,并将其与使用using语句进行了对比。通过分析IL代码,揭示了这种异常处理方式在底层的具体实现。

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

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicvoidTestEF()
{
TransactionScopeFactoryfactory
=newTransactionScopeFactory(null);
TransactionScopescope
=factory.NewTransactionScope(false);

try
{
scope.Commit();
}
catch(Exceptionee)
{
stringmsg=ee.Message;
}
finally
{
scope.Dispose();
}
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->publicvoidTestEF()
{
TransactionScopeFactoryfactory
=newTransactionScopeFactory(null);
using(TransactionScopescope=factory.NewTransactionScope(false))
{
try
{
scope.Commit();
}
catch(Exceptionee)
{
stringmsg=ee.Message;
}
}
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->.methodpublichidebysiginstancevoidTestEF()cilmanaged
{
.maxstack
2
.localsinit(
[
0]class[DataRabbit.Application]DataRabbit.Application.TransactionScopeFactoryfactory,
[
1]class[DataRabbit.Application]DataRabbit.Application.TransactionScopescope,
[
2]class[mscorlib]System.Exceptionee,
[
3]stringmsg)
L_0000:nop
L_0001:ldnull
L_0002:newobjinstance
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:callvirtinstance
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:callvirtinstance
void[DataRabbit.Application]DataRabbit.Application.TransactionScope::Commit()
L_0017:nop
L_0018:nop
L_0019:leave.sL_0027
L_001b:stloc.
2
L_001c:nop
L_001d:ldloc.
2
L_001e:callvirtinstance
string[mscorlib]System.Exception::get_Message()
L_0023:stloc.
3
L_0024:nop
L_0025:leave.sL_0027
L_0027:nop
L_0028:leave.sL_0034
L_002a:nop
L_002b:ldloc.
1
L_002c:callvirtinstance
void[DataRabbit.Application]DataRabbit.Application.TransactionScope::Dispose()
L_0031:nop
L_0032:nop
L_0033:endfinally
L_0034:nop
L_0035:ret
.
tryL_0010toL_001bcatch[mscorlib]System.ExceptionhandlerL_001btoL_0027
.
tryL_0010toL_002afinallyhandlerL_002atoL_0034
}

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

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

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

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

即类似这样:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->.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的异常处理类似这个样子:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->.try
{
.
try
{

leave L1
}
catch
{

leave L1
}

leaveL2

}
finally
{

endfinally
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值