ToList()如何在这里工作?

时间:2016-11-26 10:05:58

标签: c# linq

这可能相当微不足道但我从某个时候无法理解这一点。我需要从集合中删除一些项目。我有一个从数据库填充的模型列表。我进一步从该列表中提取了不同的集合,然后尝试删除一些项目,但它没有像我认为的那样工作

List<MyModel> temp = DbHelper.Select("Tree"); // count of temp is 40
var _doc = temp.Where(x => x.Parent == code + "02"); // count of _doc is 9
// type of _doc is System.Linq.Enumerable.WhereListIterator<MyModel>
var cd = _doc.ToList().RemoveAll(x => x.S7 == "CDFL"); // cd is 2

由于cd的值为2,因此应从_doc中删除2个项目。但_doc仍然有9个项目。

但后来我将_doc的类型更改为list,如下所示:

var _doc = temp.Where(x => x.Parent == code + "02").ToList(); // count of _doc is 9
// type of _doc is List<MyModel>
var cd = _doc.RemoveAll(x => x.S7 == "CDFL"); // cd is 2

_doc的计数是7,这是正确的。

在这两种情况下都会在一种List上调用RemoveAll,那么为什么两者的行为都不一样?

2 个答案:

答案 0 :(得分:1)

以下代码行

var _doc = temp.Where(x => x.Parent == code + "02").ToList(); 

从通过过滤的temp项中创建新列表

然后在以下一行

var cd = _doc.RemoveAll(x => x.S7 == "CDFL"); 

您从列表中删除了这些项目,结果形式为ToList

而在以下一行

var _doc = temp.Where(x => x.Parent == code + "02");

只定义一个linq查询,你不会强行执行。 _doc的类型现在是IEnumerable<T>,其中Tx的类型。为了查看哪些项目通过此过滤器,您必须强制执行该过滤器。这可以通过多种方式来完成。其中一些是以下

  • 使用foreach语句循环遍历此序列。
  • 致电ToList
  • 致电ToArray

现在关键点在以下一行:

var cd = _doc.ToList().RemoveAll(x => x.S7 == "CDFL"); 

让我们一块一块地把它拿走。正如我上面提到的,_doc.ToList()会创建一个新的Lit<T>。然后在此列表中应用RemoveAll

差异_doc与您调用ToList之前的引用相同。此外,RemoveAll已应用于通过调用ToList创建的列表。

Query Execution在此链接中您可以找到更多信息,您会在这种情况下阅读两个非常常见的术语,延迟查询执行立即查询执行

答案 1 :(得分:1)

根据msdn

  

ToList(IEnumerable)方法强制立即执行   查询评估并返回包含查询的List   结果。您可以将此方法附加到查询中以获取   缓存的查询结果副本。

因此,在第一种情况下,您要从新的List实例中删除项目,这就是为什么不从_doc集合中删除这些元素的原因。