本文通过一个简单的示例来说明在IL中进行异常处理时要注意的关键点。
我们来看一个包含try...catch...finally的示例:
{
TransactionScopeFactoryfactory=newTransactionScopeFactory(null);
TransactionScopescope=factory.NewTransactionScope(false);
try
{
scope.Commit();
}
catch(Exceptionee)
{
stringmsg=ee.Message;
}
finally
{
scope.Dispose();
}
}
这段代码实际上与使用using是等价的:
{
TransactionScopeFactoryfactory=newTransactionScopeFactory(null);
using(TransactionScopescope=factory.NewTransactionScope(false))
{
try
{
scope.Commit();
}
catch(Exceptionee)
{
stringmsg=ee.Message;
}
}
}
它们对应的IL代码如下所示:
{
.maxstack2
.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:newobjinstancevoid[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:callvirtinstanceclass[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:callvirtinstancevoid[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:callvirtinstancestring[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:callvirtinstancevoid[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块。
即类似这样:
{
.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
}
本文通过一个具体的示例详细解析了在IL(Intermediate Language)中如何实现try...catch...finally异常处理结构,并将其与使用using语句进行了对比。通过分析IL代码,揭示了这种异常处理方式在底层的具体实现。
172

被折叠的 条评论
为什么被折叠?



