C#/Unity开发中如何正确从List<int[]>类型集合移除指定int数组元素
现象说明
这是完全符合C#语言设计的预期行为。
因为数组属于引用类型,List<T>.Remove()方法默认使用引用相等性判断匹配元素:你手动new出来的target数组,哪怕元素值和列表中已有的数组完全一致,本质上是托管堆上两个完全独立的对象,持有不同的内存地址,所以相等性判断会返回false,自然无法匹配到列表中要移除的元素。
修复方案
按推荐优先级排列如下:
- 方案1:换用值类型存储坐标(最推荐)
网格坐标属于固定长度的数值集合,用值类型存储可以从根源避免引用比较的问题,同时性能更好。Unity原生提供了Vector2Int适配二维网格场景,直接替换即可:
三维网格可以用// 声明列表时修改类型 List<Vector2Int> gridPosList = new List<Vector2Int>(); // 添加元素 gridPosList.Add(new Vector2Int(0, 0)); gridPosList.Add(new Vector2Int(0, 1)); // 移除元素可直接生效 gridPosList.Remove(new Vector2Int(0, 0));Vector3Int,更高维度可以自定义readonly struct实现。 - 方案2:手动遍历匹配元素内容
如果你必须保留List<int[]>的结构,可以倒序遍历列表逐元素比较内容,匹配后调用RemoveAt移除:int[] target = new int[] {0, 0}; // 倒序遍历避免移除元素后索引偏移导致漏判 for (int i = intArrayList.Count - 1; i >= 0; i--) { // 逐元素比较内容 if (intArrayList[i][0] == target[0] && intArrayList[i][1] == target[1]) { intArrayList.RemoveAt(i); break; // 仅移除第一个匹配项加break,要移除所有匹配项则删除本行 } } - 方案3:自定义数组相等比较器
如果项目中需要频繁做int数组的内容比较,可以实现IEqualityComparer<int[]>接口复用比较逻辑:
首先定义比较器类:
移除元素时使用:public class IntArrayContentComparer : IEqualityComparer<int[]> { public bool Equals(int[] x, int[] y) { if (x == null || y == null) return x == y; if (x.Length != y.Length) return false; for (int i = 0; i < x.Length; i++) { if (x[i] != y[i]) return false; } return true; } public int GetHashCode(int[] obj) { if (obj == null) return 0; int hash = 17; foreach (int val in obj) { hash = hash * 31 + val; } return hash; } }int[] target = new int[] {0, 0}; var comparer = new IntArrayContentComparer(); var toRemove = intArrayList.FirstOrDefault(arr => comparer.Equals(arr, target)); if (toRemove != null) { intArrayList.Remove(toRemove); }
内容的提问来源于stack exchange,提问作者Amarth Gül
相关产品推荐
相关产品推荐

