在C#中能否实现类似C语言的内嵌固定大小数组?
在C#中实现类内嵌入固定大小数组的方案
要让固定大小数组直接嵌入类实例的内存中(而非作为独立堆对象),C#提供了明确的实现方式,不用完全依赖编译器的不确定优化:
1. 不安全代码中使用fixed关键字
这是最接近C++内置数组行为的方式,数组会直接嵌入类的内存布局,但需要满足两个前提:开启unsafe编译选项,且SomeType是非托管类型(即值类型且不含任何引用类型成员)。
示例代码:
private unsafe class SomeClass : SomeSuperClass { // 数组直接嵌入类实例,无额外堆分配 private fixed SomeType children[256]; // 访问示例(需在unsafe上下文中) public unsafe void SetChild(int index, SomeType value) { if (index < 0 || index >= 256) throw new ArgumentOutOfRangeException(nameof(index)); fixed (SomeType* ptr = children) { ptr[index] = value; } } }
2. 用结构体封装固定大小数组(安全代码)
如果不想使用unsafe上下文,可以定义一个包含固定大小数组的结构体,结构体的内存会嵌入到类实例中。同样要求SomeType是非托管类型(C# 10+支持结构体内部直接声明固定大小数组)。
示例代码:
// 定义固定大小数组的结构体 [StructLayout(LayoutKind.Sequential)] public struct FixedArray256<T> where T : unmanaged { private T _items[256]; // 通过Span<T>安全访问数组元素 public Span<T> AsSpan() => _items.AsSpan(); public ref T this[int index] => ref _items[index]; } // 在类中使用该结构体 private class SomeClass : SomeSuperClass { private FixedArray256<SomeType> children; // 访问示例 public void SetChild(int index, SomeType value) { if (index < 0 || index >= 256) throw new ArgumentOutOfRangeException(nameof(index)); children[index] = value; } }
关于编译器优化的补充
对于小型数组,JIT编译器可能会在Release模式下进行内联优化,将数组直接嵌入类实例中,但这种优化是不确定的——它依赖于.NET版本、数组大小、类型等因素,无法保证在所有场景下生效。如果需要稳定的内存布局,优先选择上面两种显式实现方式。
内容的提问来源于stack exchange,提问作者Tenobaal
相关产品推荐
相关产品推荐

