一个项目在迭代 IEnumerable <T>时被删除



>我有一个方法,它采用IEnumerable,进一步过滤它并循环过滤后的集合 以修改一个属性。

我观察到一种非常奇怪的行为。

当该方法循环通过过滤后的IEnumerable<Entity>时,经过几次迭代(我没有确切计算出多少(, 其中的某个项目将被删除。

private async Task<bool> UpdateSomeValue(IEnumerable<BusinessEntity> entities, BusinessEntity entityToDelete)
{
//FIlter the IENumerable
var entitiesToUpdateSequence = entities
.Where(f => f.Sequence > entityToDelete.Sequence);
if (entitiesToUpdateSequence.Any())
{
var testList = new List<FormBE>(entitiesToUpdateSequence);
Debug.WriteLine(entitiesToUpdateSequence.Count()); // 5
//DUring this loop, after a few iterations, one item gets deleted
foreach (var entity in testList)
{
entity.Sequence -= 1;
}
Debug.WriteLine(entitiesToUpdateSequence.Count()); // 4
return await _someRepo.UpdateEntitySequence(entityToDelete.Id1, entityToDelete.ID2, testList);
}
return await Task.FromResult(true);
}

该方法的调用方式如下:

var entities = await entitiesTask.ConfigureAwait(false);
var entityToDelete = entities.Single(f => f.Key.Equals("someValue"));
var updated = await UpdateSomeValue(entities, entityToDelete);

仅此而已,没有其他参考entities收藏。因此,不能从任何其他线程修改它。

我通过在列表中复制过滤的 IEnumerable,然后使用该列表进行进一步操作,暂时找到了一个单词 (循环后列表内容保持不变(。

可能导致此问题的原因是什么?

查看有关Enumerable.Where的文档。具体来说,备注。

此方法是使用延迟执行实现的。立即返回值是一个对象,用于存储执行操作所需的所有信息。在通过直接调用其 GetEnumerator 方法或在 Visual C# 中使用 foreach 或在 Visual Basic 中使用 For Each 枚举对象之前,不会执行此方法表示的查询。

这意味着,当您调用Where时,您不一定会返回一个对象,例如只有 X 个项目的ListArray。你得到一个对象,该对象知道如何根据你提供的谓词筛选你调用WhereIEnumerable<T>。当您循环访问该对象时,例如使用foreach循环或调用源中的每个项目Enumerable.Count()IEnumerable<T>将根据您提供的谓词进行评估,并且仅返回满足该谓词的项。

由于您提供的谓词会检查Sequence属性,并且您要在第一个foreach循环中修改该属性,因此第二次迭代时entitiesToUpdateSequence与您提供的谓词匹配的项较少,因此获得的计数较低。如果要递增Sequence而不是递减它,则在第二次迭代entitiesToUpdateSequence时,最终可能会得到更高的计数。

相关内容

最新更新