2 回答

TA貢獻1842條經驗 獲得超21個贊
語言規范?指出這種形式的 using 語句:
using (ResourceType resource = expression) statement
相當于:
{
? ? ResourceType resource = expression;
? ? try {
? ? ? ? statement;
? ? }
? ? finally {
? ? ? ? ((IDisposable)resource).Dispose();
? ? }
}
因此,您的 using 語句相當于:
{
? ? Animal a = new Animal();
? ? try {
? ? ? ? return a.Greeting();
? ? } finally {
? ? ? ? a.Dispose();
? ? }
}
我只能猜測為什么你認為這是違反直覺的。也許是因為您認為由于?而無法到達?finally
?那么,規范還指定:return
finally
?塊中的語句總是在控制時執行 留下?try
?語句。無論控制權轉移是否如此 發生作為正常執行的結果,作為執行的結果?break
、continue
、goto
?或?return
?語句,或作為以下結果 從?try
?語句中傳播異常。

TA貢獻1982條經驗 獲得超2個贊
該字符串在處理后返回,然后寫入控制臺。
該字符串在方法結束時返回,即在 dispose 之后返回。
“返回”是指“返回”。函數完成所有操作后返回一個變量。
這就好比一個 goto 是通過所有的finally塊到達方法的末尾,然后只在這里返回值。
在您的情況下,您的代碼相當于:
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
}
如您所見,ret 位于調用 dispose 之后的末尾。
具體來說,代碼將字符串壓入堆棧,并在返回到調用方法后將其彈出堆棧以檢索字符串。
在此示例中,控制臺寫入兩次內容并等待按鍵,然后退出該方法:
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
這與在該塊末尾調用 Dispose 的 using 塊發生的情況相同,而要返回的值位于等待調用者彈出的堆棧中。
goto的解釋是一個晦澀的解釋,如果你了解IL的話你可能會忘記它,但它可以幫助你理解。
- 2 回答
- 0 關注
- 182 瀏覽
添加回答
舉報