Search code examples
c#garbage-collectionclr

How is return by reference implemented in C#?


Given that C# GC can move memory around, how could ref-return even be implemented? Would the code below cause 'undefined behaviour'?

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

I would assume that if memory associated with _records reference moved that it would invalidate local references such as:

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

Solution

  • 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.