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

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

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

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

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

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> public void TestEF()
{
TransactionScopeFactoryfactory
= new TransactionScopeFactory( null );
using (TransactionScopescope = factory.NewTransactionScope( false ))
{
try
{
scope.Commit();
}
catch (Exceptionee)
{
string msg = ee.Message;
}
}
}

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

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> .method public hidebysiginstance void TestEF()cilmanaged
{
.maxstack
2
.localsinit(
[
0 ] class [DataRabbit.Application]DataRabbit.Application.TransactionScopeFactoryfactory,
[
1 ] class [DataRabbit.Application]DataRabbit.Application.TransactionScopescope,
[
2 ] class [mscorlib]System.Exceptionee,
[
3 ] string msg)
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_002afinally handlerL_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
}

你可能感兴趣的:(异常处理)