C#中List<int[]>元素移除失败:数独求解器开发问题
数独求解器中List<int[]>移除元素失效的问题与解决方案
为什么Remove方法无效?
int[]是引用类型,List.Remove(T item)默认用引用相等性判断:只有传入的数组对象和列表里的某个数组是同一个内存引用时,才会被移除。你新创建的new int[] {1,7}和列表里的new int[] {1,7}是两个完全独立的对象,内存地址不一样,所以Remove找不到要删除的元素。
解决方法
方法1:用RemoveAll按数组内容匹配删除
RemoveAll支持传入条件判断逻辑,遍历列表把符合条件的元素全部移除。针对你的场景,直接判断数组的列、行值是否匹配:
List<int[]> test1 = new List<int[]>(); test1.Add(new int[] { 0, 0 }); test1.Add(new int[] { 1, 7 }); // 移除列=1、行=7的空白格位置 test1.RemoveAll(arr => arr[0] == 1 && arr[1] == 7);
方法2:改用值类型存储位置(更推荐)
引用类型的相等性问题是天生的,换成值类型就能直接按内容判断相等,还能提升代码可读性。推荐两种选择:
方案A:用ValueTuple(C#7.0+支持)
轻量无需自定义类型,还能给字段命名:
// 用(列, 行)的元组存储位置 List<(int Col, int Row)> emptyCells = new List<(int, int)>(); emptyCells.Add((0, 0)); emptyCells.Add((1, 7)); // 直接按内容移除,值类型默认按内容判断相等 emptyCells.Remove((1, 7));
方案B:自定义结构体
如果需要更强的可读性或后续扩展属性,自定义结构体是更好的选择:
public struct CellPosition { public int Column { get; set; } public int Row { get; set; } // 重写Equals和GetHashCode,确保按内容判断相等 public override bool Equals(object obj) { return obj is CellPosition pos && Column == pos.Column && Row == pos.Row; } public override int GetHashCode() { return HashCode.Combine(Column, Row); } } // 使用示例 List<CellPosition> emptyCells = new List<CellPosition>(); emptyCells.Add(new CellPosition { Column = 0, Row = 0 }); emptyCells.Add(new CellPosition { Column = 1, Row = 7 }); emptyCells.Remove(new CellPosition { Column = 1, Row = 7 });
List<int[]>是不是最优方案?
不推荐用List<int[]>,原因有三个:
- 可读性差:数组索引0和1到底代表列还是行?过段时间自己都容易搞混
- 引用类型的相等性坑:就是你现在遇到的Remove失效问题
- 扩展性差:如果后续要给空白格加候选数、标记状态等,数组没法直接扩展属性
用ValueTuple或自定义结构体才是更适合的方案,既解决了相等性问题,又能提升代码的可维护性。
内容的提问来源于stack exchange,提问作者Lisa
相关产品推荐
相关产品推荐

