return by reference 如何在 C# 中实现?
How is return by reference implemented in C#?
鉴于 C# GC 可以移动内存,ref-return 怎么可能实现?下面的代码会导致 '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;
}
我假设如果与 _records 引用关联的内存发生移动,它会使本地引用无效,例如:
ref var data = ref someClassInstance.GetDataAt(0);
当GetDataAt
returns by-ref时,实际上是在使用所谓的托管指针。它们可以指向对象内部 - 在您的例子中,就像数组中的盒装结构字段一样。这就是为什么它们也被称为 内部指针 。
GC 能够在标记和重定位时正确处理它们。也就是说:
- 在标记阶段,这样的 内部指针 被识别为它指向的对象的根 - 因此您的
_records
数组不会被视为无法访问.它基本上扫描周围的内存区域以查找包含由内部指针表示的地址的对象。
- 在重定位阶段(如果发生),这样的 内部指针 会正确更新,因此它将在移动后继续指向同一对象的同一位置。
就目前的实施而言,所有这些都是基于积木和塞树机制。如果您对此感兴趣,我建议您参考my own article。
鉴于 C# GC 可以移动内存,ref-return 怎么可能实现?下面的代码会导致 '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;
}
我假设如果与 _records 引用关联的内存发生移动,它会使本地引用无效,例如:
ref var data = ref someClassInstance.GetDataAt(0);
当GetDataAt
returns by-ref时,实际上是在使用所谓的托管指针。它们可以指向对象内部 - 在您的例子中,就像数组中的盒装结构字段一样。这就是为什么它们也被称为 内部指针 。
GC 能够在标记和重定位时正确处理它们。也就是说:
- 在标记阶段,这样的 内部指针 被识别为它指向的对象的根 - 因此您的
_records
数组不会被视为无法访问.它基本上扫描周围的内存区域以查找包含由内部指针表示的地址的对象。 - 在重定位阶段(如果发生),这样的 内部指针 会正确更新,因此它将在移动后继续指向同一对象的同一位置。
就目前的实施而言,所有这些都是基于积木和塞树机制。如果您对此感兴趣,我建议您参考my own article。