首页 > 解决方案 > C#中如何实现引用返回?

问题描述

鉴于 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;
}

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

ref var data = ref someClassInstance.GetDataAt(0);

标签: c#garbage-collectionclr

解决方案


When GetDataAt returns by-ref, in fact, so-called managed pointer is being used. They can point inside objects - like a field of boxed struct inside an array, in your case. That's why they are also called interior pointers.

GC is able to handle them properly while marking and relocating. In other words:

  • during Mark phase, such an interior pointer is recognized as a root of the object it points into - thus your _records array won't be treated as unreachable. It basically scans the surrounding memory region to find an object that contains address represented by an interior pointer.
  • during Relocate phase (if it happens), such an interior pointer is updated properly so it will continue to point into the same place of the same object after moving it.

As a matter of the current implementation, all this is based on bricks and plug trees mechanism. If you are interested in it, I refer you to my own article about it.


推荐阅读