You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让每个ref struct实例拥有独立的本地数组?

解决方案

问题核心在于ref struct中的LevelInfo[]是引用类型,复制结构体时仅拷贝数组引用,导致多个实例共享同一数组内容。要实现每个实例拥有独立的嵌套状态,可通过以下两种方式解决:

方案一:基于数组的手动克隆(允许堆分配)

给Reader添加克隆方法,在复制时手动克隆整个LevelInfo数组(因LevelInfo是值类型,数组克隆会自动复制所有元素):

public ref struct Reader
{
    private struct LevelInfo
    {
        private ushort indentation;

        public int Indentation
        {
            readonly get => indentation;
            set
            {
                ArgumentOutOfRangeException.ThrowIfLessThan(value, 0);
                ArgumentOutOfRangeException.ThrowIfGreaterThan(value, 0b00111111_11111111);
                indentation = (ushort)value;
            }
        }
    }

    private LevelInfo[] levels;
    // 其他状态字段(如当前读取位置等)

    public Reader(int maxLevels)
    {
        levels = new LevelInfo[maxLevels];
        // 初始化默认状态
    }

    // 手动实现克隆逻辑
    public Reader Clone()
    {
        var cloned = this;
        // 克隆数组,生成独立的新数组实例
        cloned.levels = (LevelInfo[])this.levels.Clone();
        // 同步其他需要复制的状态字段
        // 示例:cloned.CurrentOffset = this.CurrentOffset;
        return cloned;
    }

    void SomeMethod()
    {
        levels[0].Indentation = 1;
    }
}

使用时需调用Clone方法而非直接赋值:

var original = new Reader(10);
var clonedReader = original.Clone();
// 修改clonedReader的levels不会影响original

方案二:基于Span的栈分配(无堆分配,适合预定义最大层级)

如果嵌套层级的最大值可提前确定,用Span<LevelInfo>替代数组,利用栈分配实现无堆内存开销的独立状态:

public ref struct Reader
{
    private struct LevelInfo
    {
        private ushort indentation;

        public int Indentation
        {
            readonly get => indentation;
            set
            {
                ArgumentOutOfRangeException.ThrowIfLessThan(value, 0);
                ArgumentOutOfRangeException.ThrowIfGreaterThan(value, 0b00111111_11111111);
                indentation = (ushort)value;
            }
        }
    }

    private Span<LevelInfo> levels;
    // 其他状态字段

    public Reader(int maxLevels)
    {
        // 在栈上分配固定长度的LevelInfo数组
        levels = stackalloc LevelInfo[maxLevels];
        // 初始化默认状态
    }

    public Reader Clone()
    {
        var cloned = new Reader(levels.Length);
        // 将当前层级状态复制到新的栈分配内存中
        this.levels.CopyTo(cloned.levels);
        // 同步其他状态字段
        return cloned;
    }

    void SomeMethod()
    {
        levels[0].Indentation = 1;
    }
}

这种方式避免了堆内存分配,但需注意栈内存容量限制,maxLevels不能过大(一般建议不超过千级),否则会触发栈溢出。

内容的提问来源于stack exchange,提问作者ygoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 23:47:04