LINQ 在使用 .Where() 遍历并修改 ienumerable 过滤器中的项目后,项目消失了 - 为什么?

LINQ after looping over and modifying items in enumerable filtered with .Where(), items disappear - why?

在修复一些代码的错误时,我 运行 出现了一些意外行为,似乎在遍历 IEnumerable 之后项目从它消失了。

我试图理解为什么会发生这种情况,我编写了一个小测试项目来测试这种行为。

下面简单解释一下代码,

  1. 我有一个 class (TestObject),它有一个 属性 - 一个 int
  2. 我创建了一个 TestObject 列表,并向其中添加了 5 个新的 TestObject,它们都带有 int 属性 == 5
  3. 我用 LINQ 的 .Where() 函数“过滤”列表,只获取 int == 5 的 TestObjects
    (列表中的每个元素)
  4. 我遍历 IEnumerable 的元素,将每个元素的 int 属性 设置为 0
  5. IEnumerable 现在为空
using System;
using System.Collections.Generic;
using System.Linq;

namespace TestingGroundProject
{
    class TestObject
    {
        public TestObject(int intVal)
        {
            IntVal = intVal;
        }

        public int IntVal { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<TestObject> testList = new();

            for (int i = 0; i < 5; i++)
                testList.Add(new TestObject(5));

            //this line results in expected behavior 
            //(5 elements in testEnum, all IntVal's are 0 after the loop)
            //var testEnum = testList.AsEnumerable();

            //this line results in unexpected behavior 
            //(0 elements in testEnum after the loop)
            var testEnum = testList.Where(t => t.IntVal == 5);

            //prints "5"
            Console.WriteLine(testEnum.Count());

            foreach (var t in testEnum)
                t.IntVal = 0;

            //prints "0"
            Console.WriteLine(testEnum.Count());
        }
    }
}

我猜这与 yield return 有关,它在 .Where() 的后台完成,它获取可枚举中与谓词匹配的下一个元素,我'我通过在遍历它时更改可枚举的元素来干扰它,但是有人可以 confirm/explain 这个吗?

(我确实尝试在 this link 查找有关 .Where() 函数行为的任何文档,但它并没有真正回答我的问题。)

这也是为什么 .AsEnumerable() 似乎没有这个问题的原因吗?

感谢您的宝贵时间。

IEnumerable 在您调用需要迭代的东西之前不会执行,例如您的 Count()。所以你调用 Count() 的两次序列将被单独计算。这就是物品第二次消失的原因。如果您希望将序列保持在给定点,您可以调用 ToList() 并将其保存在变量中。