问题描述
在修复一些代码的错误时,我遇到了一些意想不到的行为,似乎项目在循环后从 IEnumerable 中消失了。
我试图理解为什么会发生这种情况,我编写了一个小型测试项目来测试这种行为。
简单解释一下下面的代码,
- 我有一个类 (TestObject),它只有一个属性 - 一个 int
- 我创建了一个 TestObject 列表,并向其中添加了 5 个新的 TestObject,所有这些都具有 int 属性 == 5
- 我使用 LINQ 的 .Where() 函数“过滤”列表,只获取 int == 5 的 TestObjects
(列表中的每个元素) - 我遍历 IEnumerable 的元素,将每个元素的 int 属性设置为 0
- 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());
}
}
}
我猜这与在 .Where() 的背景中完成的 yield return 有关,它获取可枚举中与谓词匹配的下一个元素,我通过改变来干扰它迭代时可枚举的元素,但有人可以确认/解释这一点吗?
(我确实尝试在 this link 处查找有关 .Where() 函数行为的任何文档,但它并没有真正回答我的问题。)
这也是.AsEnumerable() 似乎没有这个问题的原因吗?
感谢您抽出宝贵时间。
解决方法
IEnumerable 不会执行,直到您调用需要迭代的东西,例如您的 Count()。因此,您调用 Count() 的两次序列将分别计算。这就是物品第二次消失的原因。如果您希望将序列保持在给定点,您可以调用 ToList() 并将其保存在一个变量中。