问题:try {}里有一个return语句,那么紧跟在这个try后的finally {}里的code会不会被执行,什么时候被执行,在return前还是后?
答案是会在return前执行。不过这个很容易造成误解,例如下边的代码:
static int Fun() {
var i = 0;
try {
return ++i;
}
finally {
++i;
}
}
按照finally会在return前执行,您也许会期望返回值为2,实际上返回的是1。看下il:
.method private hidebysig static int32 Fun1() cil managed
{
// Code size 22 (0x16)
.maxstack 2
.locals init ([0] int32 i,
[1] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
.try
{
IL_0003: nop
IL_0004: ldloc.0
IL_0005: ldc.i4.1
IL_0006: add
IL_0007: dup
IL_0008: stloc.0
IL_0009: stloc.1
IL_000a: leave.s IL_0013
} // end .try
finally
{
IL_000c: nop
IL_000d: ldloc.0
IL_000e: ldc.i4.1
IL_000f: add
IL_0010: stloc.0
IL_0011: nop
IL_0012: endfinally
} // end handler
IL_0013: nop
IL_0014: ldloc.1
IL_0015: ret
} // end of method Program::Fun1
简单的说,在return(C#)前会用leave.s指令跳到finally块执行,然后才真正返回(ret)。要注意的是在return前同时会把要返回的值保存在locals[1]中,而在finally块修改的是locals[0],最后返回的也是locals[1],所以finally不会修改到返回值,返回的依然是1。
实际上编译器总是会为返回值生成一个变量,我猜的,还不知道为什么。。。希望能有高人指点下。
例如这样的代码:
static Int32 Fun2() {
return 0;
}
会生成il:
.method private hidebysig static int32
Fun2() cil managed
{
// Code size 7 (0x7)
.maxstack 1
.locals init ([0] int32 CS$1$0000)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: br.s IL_0005
IL_0005: ldloc.0
IL_0006: ret
} // end of method Program::Fun2
浙公网安备 33010602011771号