【发布时间】:2014-12-22 11:24:45
【问题描述】:
我有以下代码
using System;
class Pankaj
{
public static int Main()
{
int returnValue=0;
try
{
return returnValue;
throw new Exception();
}
catch(Exception ex){
return returnValue;
}
finally
{
returnValue++;
}
return returnValue;
}
}
以上代码生成的 MSIL 是:
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
// Code size 18 (0x12)
.maxstack 2
.locals init (int32 V_0,
int32 V_1)
IL_0000: ldc.i4.0
IL_0001: stloc.0
.try
{
.try
{
IL_0002: ldloc.0
IL_0003: stloc.1
IL_0004: leave.s IL_0010
} // end .try
catch [mscorlib]System.Exception
{
IL_0006: pop
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: leave.s IL_0010
} // end handler
} // end .try
finally
{
IL_000b: ldloc.0
IL_000c: ldc.i4.1
IL_000d: add
IL_000e: stloc.0
IL_000f: endfinally
} // end handler
IL_0010: ldloc.1
IL_0011: ret
} // end of method Pankaj::Main
我有以下问题:
- 为什么 try catch 再次包含在 try 块中。
- 看起来 leave.s 的最后一行 try and catch 块指向 finally 即 IL_0010
但是在 IL_0010 行,它的 ldloc.1 我认为这意味着将局部变量 1 加载到堆栈上,然后它指向最终阻塞的方式。
是不是在位置 1 我们有 finally 块的地址。
- 如果我从 catch 块中抛出或返回某些东西,那么调用语句怎么会落到 finally 块中,它已经从 catch 块中返回,但仍然执行 finally 块。
【问题讨论】:
-
请注意 try/catch/finally 根本不会生成任何 MSIL 操作码。这些指令标识操作码的区域。这是它在后台实现方式的非常准确的表示,它生成了一个地址表。 CLR 通过查看该表来找到 catch 和 finally 子句代码。用引发异常的指令的地址对其进行索引。