Foreach 循环正确 - 使用 进行检查.Any() 返回一个错误



我有一个Guid列表,我在其中保留了项目列表中的任何重复Guid

IEnumerable<Guid> duplicateExists = ListOfMyItems
  .GroupBy(x => x.ID)
  .Where(group => group.Count() > 1)
  .Select(group => group.Key);

现在我想检查是否存在重复项,如果是,请从ListOfMyItems中删除最后一次出现。 DeleteItemFromOrder只是从数据库中删除一行。

这有效:

 foreach (var item in duplicateExists)
 {                        
     _ = ListOfMyItems.Remove(ListOfMyItems.Last(x => x.ID == item));
     MyLogic.DeleteItemFromOrder(Bill.ID, item);                      
     return;
 }

虽然这将进入条件if,然后在DeleteItemFromOrder失败,但告诉我duplicateExists - sequence contains no elements

 if(duplicateExists.Any())
 {                        
     _ = ListOfMyItems.Remove(ListOfMyItems.Last(x => x.ID == duplicateExists.First()));
     MyLogic.DeleteItemFromOrder(Bill.ID, duplicateExists.First());                      
     return;
 } 

为什么第二个示例失败?

这是 Linq延迟执行的结果:当你把

 IEnumerable<Guid> duplicateExists = ListOfMyItems
   .GroupBy(x => x.ID)
   .Where(group => group.Count() > 1)
   .Select(group => group.Key);

系统实际上不执行查询;然后你有

if (duplicateExists.Any())
{                        
    _ = ListOfMyItems.Remove(ListOfMyItems.Last(x => x.ID == duplicateExists.First()));
    MyLogic.DeleteItemFromOrder(Bill.ID, duplicateExists.First());                      
    return;
} 

系统执行以下操作:

  1. 执行duplicateExists.Any()并获取true,因为存在重复项
  2. 执行duplicateExists.First()获取副本并将其ListOfMyItems中删除 - ListOfMyItems.Remove
  3. 尝试再次执行duplicateExists.First() MyLogic.DeleteItemFromOrder,现在失败,因为ListOfMyItems已被修改并且没有重复项 - duplicateExists为空

快速补丁:具体化duplicateExists强制系统执行查询并将结果存储在集合中,例如数组:

  IEnumerable<Guid> duplicateExists = ListOfMyItems
   .GroupBy(x => x.ID)
   .Where(group => group.Count() > 1)
   .Select(group => group.Key)
   .ToArray();

LINQ 使用惰性求值。在使用物理列表修改原始数据集之前,您需要将初始查询解析为物理列表,如下所示:

var duplicateExists = ListOfMyItems
  .GroupBy(x => x.ID)
  .Where(group => group.Count() > 1)
  .Select(group => group.Key)
  .ToArray();

最新更新