为什么在 finally 部分重置此变量时,在 try 块中返回变量不会更改返回事物的值?

最短胡子定理

我不太明白以下代码中的指令是如何流动的。的主体finally保证在方法返回之前执行。如果是这样,返回值应该是 0 而不是 1。

您能否解释为什么即使finally已将其重置为 0返回值仍为 1 的内部机制

class Container
{
    int data = 0;
    public int Retrieve()
    {
        try
        {
            Inc();
            return data;
        }
        finally
        {
            Reset();
            //return data;
        }
    }
    void Reset()
    {
        data = 0;
        WriteLine("Reset");
    }
    void Inc() => data++;
}

class ReturnInTry
{
    static void Main()
    {
        Clear();
        WriteLine("Start");
        WriteLine(new Container().Retrieve());
        WriteLine("End");
    }
}
奥利维尔·罗吉尔

因为在执行返回指令时,它会将要返回的值压入 CPU 堆栈。

然后执行 finally 块,但它不会修改已经推送的值。

因此,在方法 PROC RET 之后,调用者弹出该值并拥有它已被推送的内容,但数据本身已被重置。

因此,再次调用该方法将返回 0。

这意味着先执行return语句,然后finally执行in的代码,所以结果是之前存储的,改变data不会改变这个存储在堆栈中的结果。

try-finally(C# 参考)

我们可以使用例如 ILSpy 来检查:

.method public hidebysig 
  instance int32 Retrieve () cil managed 
{
  // Method begins at RVA 0x4cf4
  // Code size 30 (0x1e)
  .maxstack 1
  .locals init ( [0] int32 )

  .try
  {
    // Inc();
    IL_0002: ldarg.0
    IL_0003: call instance void ConsoleApp.Container::Inc()

    // return data;
    IL_0009: ldarg.0
    IL_000a: ldfld int32 ConsoleApp.Container::data
    IL_000f: stloc.0

    IL_0010: leave.s IL_001c
  } // end .try
  finally
  {
    // Reset();
    IL_0013: ldarg.0
    IL_0014: call instance void ConsoleApp.Container::Reset()
    // }
    IL_001b: endfinally
  } // end handler

  IL_001c: ldloc.0
  IL_001d: ret
} // end of method Container::Retrieve

OpCodes.Stloc_0 字段

OpCodes.ldloc_0 字段

// Console.WriteLine(new Container().Retrieve());
IL_000c: newobj instance void ConsoleApp.Container::.ctor()
IL_0011: call instance int32 ConsoleApp.Container::Retrieve()
IL_0016: call void [mscorlib]System.Console::WriteLine(int32)

OpCodes.Call 字段

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么在finally块中更改返回的变量不会更改返回值?

最终总是在try块中的return之前运行,那么为什么finally块中的更新不影响try块返回的变量的值?

Java并发Hashmap initTable()为什么try / finally块?

为什么JavaScript的try / finally块会导致函数明显返回两次?

为什么try..catch..finally块的finally节在catch之前运行?

即使我从Try :: Tiny的finally块返回了值,为什么仍收到“使用未初始化的值”警告?

部分重叠的try-finally块

为什么在try块中使用return仍要执行finally块中的语句

在java中返回try-catch的finally块。这个例子有什么好处吗?

为什么不能在try / catch块中访问变量?

为什么Java stacktrace仅在finally块中返回失败?

为什么try-finally有效,而不是try-else-finally?

什么时候应该在Java的try-catch-finally中使用finally块

在C#中,为什么在finally块的开头未明确分配变量?

使用Try,catch,finally的局部变量未分配问题

当涉及来自finally块的返回值时,在try块中具有return语句是一种好习惯吗

为什么finally块在抛出异常时可能不会执行?

Java在try-catch-finally机制中的返回值

Python与try-except-finally中的返回值混淆

使用try:捕获异常时,为什么不能返回?

在Java中try-catch-finally块

在try块结束之前执行finally块

java try块内定义的变量的作用域是什么?为什么在try块之外无法访问它?

在try-finally块中等待

为什么try-with-resources无法使用字段变量?

为什么try块在Kotlin中不返回lambda表达式中的值?

在Python的try块中使用finally的实际示例可能是什么

在必须释放连接时,使用try / except / finally的pythonic方法是什么?

Scala 中的 try-finally 问题