遍历集合副本时修改原集合仍报错,求标准处理方案
问题分析与解决方案
你的核心问题是没有真正创建集合的副本——retVal_copy = retVal;这行代码只是把retVal的引用赋值给了retVal_copy,两者指向内存中同一个List实例。所以当你在遍历retVal_copy时修改retVal,本质上还是在修改正在遍历的集合,自然会触发“Collection was Modified”异常。
正确的处理步骤
1. 创建真正的独立副本
要创建List的副本,需要生成一个新的List实例,把原集合的元素复制进去,常用两种方式:
- 使用
ToList()方法:var retVal_copy = retVal.ToList(); - 调用List的构造函数:
var retVal_copy = new List<ThisModel>(retVal);
这两种方式都会生成一个全新的List,和原集合互相独立,遍历副本时修改原集合不会触发异常。
2. 修正后的代码示例
List<ThisModel> retVal = []; // 初始化retVal的逻辑 // 创建真正的副本 List<ThisModel> retVal_copy = retVal.ToList(); foreach(ThisModel item in retVal_copy) { if(some_condition) { // 初始化新元素 retVal.Add(new_item); } } // 如果后续需要再次循环,必须重新基于当前retVal创建新副本 retVal_copy = retVal.ToList(); // 这里可以安全执行下一轮遍历逻辑
标准处理思路
当需要遍历集合同时修改原集合时,遵循以下原则:
- 遍历的必须是原集合的独立副本,而非引用赋值的变量
- 如果需要多次执行“遍历+修改”操作,每次遍历前都要重新创建当前原集合的副本(因为原集合已经被修改过,旧副本无法反映最新状态)
- 若场景允许,也可以先收集所有需要添加的元素,最后一次性批量添加到原集合,这样效率更高:
List<ThisModel> newItems = []; foreach(ThisModel item in retVal) { if(some_condition) { newItems.Add(new_item); } } retVal.AddRange(newItems);
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

