【问题标题】:Foreach loop doesn't iterate over entire IEnumerableForeach 循环不会遍历整个 IEnumerable
【发布时间】:2016-04-08 15:16:19
【问题描述】:

我的 foreach 循环没有遍历整个集合,只是第一个元素,我不知道为什么。我发现的唯一类似问题是:IEnumerable not enumerating in foreach

但唯一的答案是由问题作者发布的,他谈到 IEnumerable 有超时,这对我来说真的没有意义,而且我以前从未听说过。

IEnumerable<Document> documentsToAdd = dbEvent.Documents.Where(
    dbd => !eventToSave.Documents.Select(d => d.DocumentId)
    .Contains(dbd.DocumentId));
foreach (Document documentToAdd in documentsToAdd) {
    documentToAdd.DocumentType = null;
    documentToAdd.DeletedByUser = null;
    documentToAdd.DocumentOwnerTeam = null;
    documentToAdd.UploadedByUser = null;
    documentToAdd.UploadedInStage = null;
    hcDbContext.Documents.Add(documentToAdd);
}

在调试器中,我可以看到 documentsToAdd 在集合中有 3 个元素。但是当我单步执行循环时,它只执行一次然后继续,因此只保存第一个文档。由于我已经验证了documentsToAdd 的内容,我知道问题不在Where 子句中。为什么foreach 不浏览整个集合?

编辑

需要明确的是,没有抛出异常。它通过循环一次,然后移动到foreach 之后的下一行。

【问题讨论】:

  • 您遇到异常了吗?在 try 子句中包装代码。
  • 你怎么知道枚举中有不止一项?
  • 什么是eventToSave?就像第一次平底船一样,尝试在documentsToAdd 上添加ToList(),看看是否会有所不同。
  • @CodingGorilla 我在documentToAdd.DocumentType = null 行上放了一个断点。然后我在documentsToAdd 上做了一个快速手表,显示计数为 3。我还进入了 3 个元素中的每一个元素并检查了它们,它们的属性已完全填充。
  • 它是一只黑森虫。你改变你观察到的,调试器清空了可枚举的。

标签: c# .net


【解决方案1】:

IEnumerable 是一个迭代器,因此它一次返回一个结果。

每次 foreach 循环时,它都会向迭代器询问下一个结果。有时结果可能会从正在枚举的集合中消失,因此您会遇到意外行为。

为避免这种情况,请确保在开始 foreach 之前获得所有结果,方法是调用 .ToList()

  // Make a list of all documents
  List<Document> documentsToAdd;

  documentsToAdd = dbEvent.Documents
                          .Where(dbd => !eventToSave.Documents
                                                    .Select(d => d.DocumentId)
                                                    .Contains(dbd.DocumentId))
                          .ToList();   // load all results

  // Now this will loop through the whole list
  foreach (Document documentToAdd in documentsToAdd) 
  {
      documentToAdd.DocumentType = null;
      documentToAdd.DeletedByUser = null;
      documentToAdd.DocumentOwnerTeam = null;
      documentToAdd.UploadedByUser = null;
      documentToAdd.UploadedInStage = null;

      hcDbContext.Documents.Add(documentToAdd);
  }

【讨论】:

  • 您能解释一下为什么会这样吗?正如我在上面问过的克里斯,为什么我不能可靠地枚举一个 IEnumerable?我说可靠是因为它在过去几天一直运行良好,并且今天才开始这样做。为什么需要 ToList() 转换?
  • @Legion 尝试删除 ToList(),使用调试器开始执行,跟踪到 foreach 循环结束,然后枚举可枚举的对象
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2017-11-23
  • 2013-12-16
  • 2017-08-29
  • 1970-01-01
相关资源
最近更新 更多