为什么使用添加范围将列表添加到另一个列表,从第一个列表中删除元素?

时间:2013-08-20 19:52:23

标签: c# linq ienumerable addrange

考虑以下示例:

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填充了两个元素之前

2 个答案:

答案 0 :(得分:11)

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

groupsToAdd实际上不会迭代源序列(groups1)或执行谓词检查(这取决于groups2的状态),直到它被迭代。 / p>

您迭代groupsToAdd两次。拨打AddRange后,再次拨打Dump。第二次迭代它group2已经改变,因此查询结果也发生了变化。

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

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

这将在当时评估查询,以便groupsToAdd代表查询的结果而不是查询本身

答案 1 :(得分:8)

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