为什么我可以 return 引用局部变量的字段

Why can I return a reference to a local variable's field

The documentation on ref returns and ref locals 状态:

The return value must have a lifetime that extends beyond the execution of the method. In other words, it cannot be a local variable in the method that returns it. It can be an instance or static field of a class, or it can be an argument passed to the method. Attempting to return a local variable generates compiler error CS8168, "Cannot return local 'obj' by reference because it is not a ref local."

我以为我明白了。我想如果我 return 编辑了对局部变量的引用,那么该变量可能会被收集,因此我的引用不再引用变量。

但是,我今天了解到我可以创建一个局部变量,然后 return 对该局部变量上的字段的引用。举例说明:

using System;

namespace IAmConfused
{
   class Program
   {
      static void Main(string[] args)
      {
         var foo = new Foo();
         ref int barInt = ref foo.GetInt();
         Console.WriteLine(barInt); //Outputs 123

         barInt = 354;
         Console.WriteLine(barInt); //Outputs 354
      }
   }

   public class Foo
   {
      public ref int GetInt()
      {
         // int x = 123;
         // return ref x; //CS8168
         var bar = new Bar(123);
         return ref bar.Value;
      }

      class Bar
      {
         public Bar(int v)
         {
            Value = v;
         }

         public int Value;
      }
   }
}

这与 return本地人有什么不同?局部变量 bar 可能会在 GetInt return 秒后被收集,对吧?那么如果发生这种情况,barInt 引用的是什么?

我已经尝试了 C# 版本 7.0、7.1、7.2 和 7.3,它适用于所有版本。

考虑这个代码示例:

void Foo()
{
    object a;
    int b;
}

这两个变量都保存在堆栈中。是的,它们确实是,甚至是对象。变量 a 是指向对象的指针,而不是对象本身,并且该指针确实是堆栈上的局部变量。

因此,如果您 return 对其中任何一个的引用,它将是对堆栈中某个变量的引用。当调用 returns 时,堆栈当然会被覆盖,这就是为什么你不能引用 return 本地的原因。

另一方面,考虑这个例子:

class Bar
{
    public int SomeInteger;
}

void Foo()
{
    Bar c = new Bar();
}

在这种情况下,c 也保存在堆栈中。但是它引用的对象在堆上,它的字段 SomeInteger 也是如此。所以你可以安全地 return 引用 SomeInteger 因为它存在于堆上并且当方法 returns.

时堆不会被覆盖