考虑以下示例:
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填充了两个元素之前
答案 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现在包含它们不再是原始查询结果的元素。