我有以下代码
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
我有以下问题:
答案 0 :(得分:10)
为什么try catch再次包含在try块中。
对此不确定。它可能只是ildasm
选择反编译它的方式。 ECMA-335表示SEHClause
之后TryBlock
元素的指定方式存在限制,但我还没有找到这些限制。
看起来像leave.sill和catch块的最后一行是指向最后即IL_0010但是在行IL_0010它的ldloc.1我认为这意味着在堆栈上加载局部变量1,然后它如何指向finally块。它是在位置1,我们有finally块的地址。
不,在<{em} finally
块之后跳转到 - 有效地返回值。你没有得到很多的返回语句并且返回相同的东西以及无法访问的代码并没有帮助,但我相信这一点基本上只是为了移动{{ 1}}在ret
和try
之外。我认为编译器正在为返回值有效地设置一个额外的局部变量。
如果我从catch块中抛出或返回一些内容,那么调用语句如何落入finally块,它已经从catch块返回,但仍然会执行finally块。
如何定义C#和IL - catch
块将被执行但是你退出块。
答案 1 :(得分:2)
Jon Skeet已经回答了最后两个问题,所以我只关注第一个问题。
为什么try catch再次包含在try块中。
这有几个原因: