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
相关产品推荐
相关产品推荐

