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

C#中struct实现的PlanetChunk树无法更新节点meshStartIndex问题咨询

问题根因
  • 核心原因是PlanetChunk被定义为值类型(struct):C#中值类型默认按值传递,你使用foreach(PlanetChunk child in children)遍历数组时,每次取到的child都是数组内原元素的拷贝。你对拷贝对象的meshStartIndex做修改,只会作用在临时拷贝上,不会同步更新到children数组存储的原实例,因此递归结束后访问原数组元素看不到修改效果。
  • 你贴出的递归代码存在语法错误:children.OffsetMeshStartIndexRec(threshold, offset)这行调用对象是PlanetChunk数组,数组本身没有这个方法,你应该调用的是遍历得到的child实例的对应方法。
修复方案

方案1(推荐):将PlanetChunk改为引用类型

树结构这类需要递归修改自身属性的场景,天然更适合用class实现,引用类型传递的是对象指针,修改会直接作用在原实例上:

// 把struct改成class即可
public class PlanetChunk
{
    public PlanetChunk[] children;
    public bool isLeaf;
    private int meshStartIndex;
    private int meshLength;

    public void OffsetMeshStartIndexRec(int threshold, int offset)
    {
        Console.WriteLine($"BEFORE : start : {meshStartIndex}, length : {meshLength}");

        if(meshStartIndex > threshold)
        {
            meshStartIndex += offset;
        }

        Console.WriteLine($"AFTER : start : {meshStartIndex}, length : {meshLength}");

        if(!isLeaf)
        {
            foreach(PlanetChunk child in children)
            {
                child.OffsetMeshStartIndexRec(threshold, offset);
            }
        }
    }
}

方案2:强制保留struct的修改方式

如果因为性能等原因必须使用struct,可以放弃foreach,改用for循环手动更新数组内的元素:

if(!isLeaf)
{
    for(int i = 0; i < children.Length; i++)
    {
        // 取出元素修改后再写回数组
        var temp = children[i];
        temp.OffsetMeshStartIndexRec(threshold, offset);
        children[i] = temp;
    }
}

如果使用C# 7.2及以上版本,也可以给struct方法加上ref修饰,避免创建值类型副本:

public ref void OffsetMeshStartIndexRec(int threshold, int offset)
{
    // 方法内部逻辑保持不变
}

内容的提问来源于stack exchange,提问作者LucioleMaléfique

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 02:36:05