如何在C#中实现按引用返回?

Abs*_*ero 2 c# clr garbage-collection

鉴于C#GC可以移动内存,甚至如何实现ref-return?下面的代码会导致“未定义的行为”吗?

public struct Record
{
    public int Hash;
    public VeryLargeStruct Data;
}

public class SomeClass
{
    private Record[] _records = new Record[16];
    public ref VeryLargeStruct GetDataAt(int index) =>
                    ref _records[index].Data;
}
Run Code Online (Sandbox Code Playgroud)

我假设如果与_records引用相关联的内存移动了,它将使本地引用无效,例如:

ref var data = ref someClassInstance.GetDataAt(0);
Run Code Online (Sandbox Code Playgroud)

Kon*_*osa 6

GetDataAt实际上,当返回by-ref时,正在使用所谓的托管指针。它们可以指向对象内部-在您的情况下,就像数组中的框式结构字段一样。这就是为什么它们也被称为内部指针

GC可以在标记和重新放置时正确处理它们。换一种说法:

  • 在标记阶段,这样的内部指针被识别为它所指向的对象的根-因此,您的_records数组不会被视为不可访问的。它基本上会扫描周围的内存区域以找到包含内部指针表示的地址的对象。
  • 在“重定位”阶段(如果发生),此类内部指针会正确更新,因此在移动该对象后它将继续指向同一对象的同一位置。

就当前的实现而言,所有这一切都是基于砖和塞树机制。如果您对此感兴趣,请参考我自己的文章