5

考虑以下示例:

IEnumerable<Int32> groupsToAdd = new List<Int32>();

List<Int32> groups1 = new List<Int32>() { 1,2,3 };
List<Int32> groups2 = new List<Int32>() { 3,4,5 };

groupsToAdd = groups1.Where(g => false == groups2.Contains(g));

groups2.AddRange(groupsToAdd);

groupsToAdd.Dump();

groupsToAdd.Dump()被调用时,列表现在是空的。我查看了 AddRange 参考,它没有提到元素已从列表中删除,但是当我测试此代码(在 linqpad 中)时,它以空结尾。为什么是这样?

编辑:为了澄清,我的意思是元素被删除,groupsToAdd因为在groups2.AddRange(groupsToAdd)groupsToAdd 之前填充了两个元素

4

2 回答 2

14

重要的是要记住,在使用 LINQ 时,它会产生一个查询,而不是那个查询的结果groupsToAdd不是项目列表,它只是能够在需要时获取一些项目的查询的定义。

groupsToAdd在迭代之前实际上并不迭代源序列(即groups1)或执行谓词检查(取决于 的状态groups2)。

你迭代groupsToAdd两次。一次调用 to AddRange,再次调用 to Dump。第二次迭代时它group2发生了变化,因此查询的结果也发生了变化。

如果您想避免这种延迟执行,那么您可以通过将代码修改为以下内容来立即实现查询:

groupsToAdd = groups1.Where(g => false == groups2.Contains(g));
    .ToList();

这将在那个时刻及时评估查询,以便groupsToAdd表示查询的结果而不是查询本身

于 2013-08-20T19:57:49.917 回答
10

这是因为 IEnumerable。当您将 groupsToAdd 设置groups1.Where(g => false == groups2.Contains(g))为延迟执行的结果时,这意味着查询直到 AddRange() 才运行,然后在 Dump() 再次运行。因为列表 groups2 现在包含不再是原始查询结果的元素。

于 2013-08-20T19:55:37.753 回答