这可能相当微不足道但我从某个时候无法理解这一点。我需要从集合中删除一些项目。我有一个从数据库填充的模型列表。我进一步从该列表中提取了不同的集合,然后尝试删除一些项目,但它没有像我认为的那样工作
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,那么为什么两者的行为都不一样?
答案 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>
,其中T
是x
的类型。为了查看哪些项目通过此过滤器,您必须强制执行该过滤器。这可以通过多种方式来完成。其中一些是以下
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集合中删除这些元素的原因。