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

本文关键字:列表 添加 另一个 元素 删除 第一个 范围 为什么 一个 | 更新日期: 2023-09-27 18:28:20

考虑以下示例:

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

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

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

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

您迭代groupsToAdd两次。一次是呼叫AddRange,另一次是调用Dump。第二次迭代时,group2发生了变化,因此查询的结果也发生了变化。

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

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

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

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