2 回答

TA貢獻(xiàn)1842條經(jīng)驗(yàn) 獲得超21個(gè)贊
語(yǔ)言規(guī)范?指出這種形式的 using 語(yǔ)句:
using (ResourceType resource = expression) statement
相當(dāng)于:
{
? ? ResourceType resource = expression;
? ? try {
? ? ? ? statement;
? ? }
? ? finally {
? ? ? ? ((IDisposable)resource).Dispose();
? ? }
}
因此,您的 using 語(yǔ)句相當(dāng)于:
{
? ? Animal a = new Animal();
? ? try {
? ? ? ? return a.Greeting();
? ? } finally {
? ? ? ? a.Dispose();
? ? }
}
我只能猜測(cè)為什么你認(rèn)為這是違反直覺(jué)的。也許是因?yàn)槟J(rèn)為由于?而無(wú)法到達(dá)?finally
?那么,規(guī)范還指定:return
finally
?塊中的語(yǔ)句總是在控制時(shí)執(zhí)行 留下?try
?語(yǔ)句。無(wú)論控制權(quán)轉(zhuǎn)移是否如此 發(fā)生作為正常執(zhí)行的結(jié)果,作為執(zhí)行的結(jié)果?break
、continue
、goto
?或?return
?語(yǔ)句,或作為以下結(jié)果 從?try
?語(yǔ)句中傳播異常。

TA貢獻(xiàn)1982條經(jīng)驗(yàn) 獲得超2個(gè)贊
該字符串在處理后返回,然后寫入控制臺(tái)。
該字符串在方法結(jié)束時(shí)返回,即在 dispose 之后返回。
“返回”是指“返回”。函數(shù)完成所有操作后返回一個(gè)變量。
這就好比一個(gè) goto 是通過(guò)所有的finally塊到達(dá)方法的末尾,然后只在這里返回值。
在您的情況下,您的代碼相當(dāng)于:
static string Invoker()
{
string result;
using (Animal a = new Animal())
{
result = a.Greeting();
goto end;
// a return here is like a "goto end"
// done after invoking the Dispose()
// while exiting the using block
}
// others things possible here
// return anything_else_here;
end:
return result;
}
下面是 VS2017 生成的 IL 代碼(使用 .NET Reflector):
.method private hidebysig static string Invoker() cil managed
{
.maxstack 1
.locals init (
[0] class ConsoleApp1.Animal a,
[1] string str)
L_0000: nop
L_0001: newobj instance void ConsoleApp1.Animal::.ctor()
L_0006: stloc.0
L_0007: nop
L_0008: ldloc.0
L_0009: callvirt instance string ConsoleApp1.Animal::Greeting()
L_000e: stloc.1
L_000f: leave.s L_001c
L_0011: ldloc.0
L_0012: brfalse.s L_001b
L_0014: ldloc.0
L_0015: callvirt instance void [mscorlib]System.IDisposable::Dispose()
L_001a: nop
L_001b: endfinally
L_001c: ldloc.1
L_001d: ret
.try L_0007 to L_0011 finally handler L_0011 to L_001c
}
如您所見(jiàn),ret 位于調(diào)用 dispose 之后的末尾。
具體來(lái)說(shuō),代碼將字符串壓入堆棧,并在返回到調(diào)用方法后將其彈出堆棧以檢索字符串。
在此示例中,控制臺(tái)寫入兩次內(nèi)容并等待按鍵,然后退出該方法:
static string Test()
{
try
{
try
{
return "a string"; // the string is pushed in the stack here
}
finally
{
Console.WriteLine("1");
Console.ReadKey();
// no other return allowed here
}
}
finally
{
Console.WriteLine("2");
Console.ReadKey();
// no other return allowed here
}
}
// The method that calls Test() next pop the stack to retreive the string
這與在該塊末尾調(diào)用 Dispose 的 using 塊發(fā)生的情況相同,而要返回的值位于等待調(diào)用者彈出的堆棧中。
goto的解釋是一個(gè)晦澀的解釋,如果你了解IL的話你可能會(huì)忘記它,但它可以幫助你理解。
- 2 回答
- 0 關(guān)注
- 176 瀏覽
添加回答
舉報(bào)