C# List添加PotentialSolution实例均为最后一个元素的问题排查
问题根因
初始代码错误
PotentialSolution属于C#引用类型,你在循环中始终修改同一个ps实例,possibleTracks.Add(ps)仅向列表中添加该实例的引用,并未生成新的对象副本。循环结束后列表内所有元素都指向同一个实例,值自然全为最后一次修改的结果。
副本方案无效的错误
你实现的PotentialSolution拷贝构造函数没有对board数组做深拷贝:数组本身也是引用类型,如果你在拷贝构造中仅做this.board = ps.board这类赋值,所有新实例的board还是指向同一块内存空间,修改任意一个实例的board单元格值,所有实例的对应值都会同步变更,这就是你测试代码永远无法进入分支的原因。
修复方案
- 修改
PotentialSolution的拷贝构造函数,对board数组实现深拷贝:
public class PotentialSolution { // 原有成员定义保持不变 // 正确的拷贝构造函数 public PotentialSolution(PotentialSolution other) { // 值类型成员直接拷贝 nextSide = other.nextSide; h = other.h; w = other.w; // 二维数组深拷贝 int rowCount = other.board.GetLength(0); int colCount = other.board.GetLength(1); board = new Track[rowCount, colCount]; for (int i = 0; i < rowCount; i++) { for (int j = 0; j < colCount; j++) { board[i, j] = other.board[i, j]; } } // 静态成员属于类共有,不需要拷贝 } }
- 你后续修改的循环逻辑无需调整,拷贝构造修复后即可正常生成独立的实例副本。测试代码中不需要再对列表取出的元素做二次拷贝,直接判断即可:
if (possibleTracks.Count >= 2) { var ps1 = possibleTracks.First(); var ps2 = possibleTracks.Last(); if (ps1.GetCell() != ps2.GetCell()) { // 现在可以正常进入该分支 int foo = 1; } }
内容的提问来源于stack exchange,提问作者quilkin
相关产品推荐
相关产品推荐

