错误:集合已修改;枚举操作可能无法执行

本文关键字:执行 操作 枚举 集合 修改 错误 | 更新日期: 2023-09-27 17:58:18

我一直在字段中处理这个异常。我不明白在迭代时如何修改集合。在方法开始时,我将所有内容复制到局部变量中。

  public void Flush() {
            var tempEntities = attachedEntities.Select(item => item).ToList();
            attachedEntities.Clear();
            var tempEntitiesToDelete = entitiesToDelete.Select(item => item).ToList();
            entitiesToDelete.Clear();
            foreach (var attachedEntity in tempEntities) {
                var isTransient = (bool)GetPrivateField(attachedEntity.GetType(), attachedEntity, "isTransient");
                if (isTransient)
                    db.Insert(attachedEntity);
                else
                    db.Update(attachedEntity);
            }
            foreach (var entity in tempEntitiesToDelete)
                db.Delete(entity);
        }

堆栈跟踪

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
  at System.Collections.Generic.List`1 Enumerator[Compass.Mobile.Core.DataAccess.IEntity].VerifyState () [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1 Enumerator[Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 
  at System.Linq.Enumerable <CreateSelectIterator>c__Iterator1D`2[Compass.Mobile.Core.DataAccess.IEntity,Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1[Compass.Mobile.Core.DataAccess.IEntity].AddEnumerable (IEnumerable`1 enumerable) [0x00000] in <filename unknown>:0 
  at System.Collections.Generic.List`1[Compass.Mobile.Core.DataAccess.IEntity]..ctor (IEnumerable`1 collection) [0x00000] in <filename unknown>:0 
  at System.Linq.Enumerable.ToList[TSource] (IEnumerable`1 source) [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.DataAccess.Session.Flush () [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.DataAccess.Session.Commit () [0x00000] in <filename unknown>:0 
  at Compass.Mobile.Core.Bootstrap.CommandBus.Flush () [0x00000] in <filename unknown>:0 

错误:集合已修改;枚举操作可能无法执行

替换此:

foreach (var entity in tempEntitiesToDelete)
     db.Delete(entity);

带有:

for (var i = tempEntitiesToDelete.Count - 1; i >= 0; i--)
   db.Delete(tempEntitiesToDelete[i]);

当我在循环浏览时试图删除时,我遇到了这个问题;它正试图修改项目列表。因此,向后循环为我修复了它。

根据堆栈跟踪判断,当Select迭代器的底层列表在移动到下一项之前检查其状态时,它在foreach(或枚举作为普通列表的tempEntities)内部并没有失败,而是在其中一个ToList调用内部失败。

你的堆栈跟踪中的这一行让我相信:

at System.Linq.Enumerable <CreateSelectIterator>c__Iterator1D`2[Compass.Mobile.Core.DataAccess.IEntity,Compass.Mobile.Core.DataAccess.IEntity].MoveNext () [0x00000] in <filename unknown>:0 

foreach循环变量只是一个列表,所以它不经过Select。这让我相信attachedEntitiesentitiesToDelete在对它们执行Select时会发生变化:

/* Failing here... */
var tempEntities = attachedEntities.Select(item => item).ToList();
attachedEntities.Clear();
/* ...or here*/
var tempEntitiesToDelete = entitiesToDelete.Select(item => item).ToList();
entitiesToDelete.Clear();
/* ...but not here! */
foreach (var attachedEntity in tempEntities) {
   // ...
}

这很可能是一个并发问题。

顺便说一句,你真的不需要Select (item => item),它只是一个身份投影。