在 C# 中,我注意到如果我在 LINQ 上运行 foreach 循环生成 IEnumerable<T>
集合并尝试修改每个 T 元素的内容,我的修改不是持久的。
另一方面,如果我应用 ToArray()
或 ToList()
创建我的集合时的方法,foreach 循环中单个元素的修改是持久的。
我怀疑这在某种程度上与延迟执行有关,但具体如何对我来说并不完全清楚。我真的很感激对这种行为差异的解释。
这是一些示例代码 - 我有一个类 MyClass
带有构造函数和自动实现的属性:
public class MyClass
{
public MyClass(int val) { Str = val.ToString(); }
public string Str { get; set; }
}
在我的示例应用程序中,我使用 LINQ Select()
创建 MyClass
的两个集合基于整数集合的对象,一个 IEnumerable<MyClass>
, 和一个 IList<MyClass>
通过应用 ToList()
最后的方法。
var ints = Enumerable.Range(1, 10);
var myClassEnumerable = ints.Select(i => new MyClass(i));
var myClassArray = ints.Select(i => new MyClass(i)).ToList();
接下来,我对每个集合运行一个 foreach 循环,并修改循环的 MyClass
的内容。对象:
foreach (var obj in myClassEnumerable) obj.Str = "Something";
foreach (var obj in myClassArray) obj.Str = "Something else";
最后,我输出 Str
每个集合中第一个元素的成员:
Console.WriteLine(myClassEnumerable.First().Str);
Console.WriteLine(myClassArray.First().Str);
有点违反直觉,输出是:
1
Something else
最佳答案
延迟执行确实是关键点。
执行 myClassEnumerable.First().Str
将重新执行您的查询 ints.Select(i => new MyClass(i));
所以它会给您一个带有新整数列表的新 IEnumerable。
您可以使用调试器查看实际情况。在 IEnumerable select 的 new MyClass(i)
部分放置一个断点,当您为 Console.WriteLine 执行它时,您将看到这部分再次被击中
关于IEnumerable 与 List 上的 C# foreach - 元素修改仅对数组持久 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8064395/