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

Let*_*nch 4 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();
Run Code Online (Sandbox Code Playgroud)

groupsToAdd.Dump()调用时,列表现在为空.我查了一下AddRange引用并没有提到从列表中删除元素但是当我测试这段代码时(在linqpad中)它结束为空.为什么是这样?

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

Ser*_*rvy 12

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

groupsToAdd实际上并不迭代源序列(即groups1)或执行谓词检查(取决于状态groups2),直到它被迭代.

你迭代groupsToAdd两次.一旦打电话AddRange,再打电话给Dump.第二次迭代时它group2已经改变,因此查询结果也发生了变化.

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

groupsToAdd = groups1.Where(g => false == groups2.Contains(g));
    .ToList();
Run Code Online (Sandbox Code Playgroud)

这将在该时刻评估查询,以便groupsToAdd表示查询结果而不是查询本身.


Dav*_*ork 8

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