And*_*son 3 c# ienumerable foreach reference
在C#中,我注意到如果我在LINQ生成的IEnumerable<T>集合上运行foreach循环并尝试修改每个T元素的内容,我的修改就不会持久.
另一方面,如果我在创建集合时应用ToArray()or ToList()方法,则对foreach循环中各个元素的修改是持久的.
我怀疑这在某种程度上与延迟执行有关,但究竟对我来说并不完全是显而易见的.我真的很感激这种行为差异的解释.
这是一些示例代码 - 我有一个MyClass带有构造函数和自动实现属性的类:
public class MyClass
{
public MyClass(int val) { Str = val.ToString(); }
public string Str { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在我的示例应用程序中,我使用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();
Run Code Online (Sandbox Code Playgroud)
接下来,我在每个集合上运行一个foreach循环,并修改循环MyClass对象的内容:
foreach (var obj in myClassEnumerable) obj.Str = "Something";
foreach (var obj in myClassArray) obj.Str = "Something else";
Run Code Online (Sandbox Code Playgroud)
最后,我输出Str每个集合中第一个元素的成员:
Console.WriteLine(myClassEnumerable.First().Str);
Console.WriteLine(myClassArray.First().Str);
Run Code Online (Sandbox Code Playgroud)
有点违反直觉,输出是:
1
Something else
Run Code Online (Sandbox Code Playgroud)
Wou*_*ort 13
延期执行确实是关键点.
执行myClassEnumerable.First().Str将重新执行您的查询ints.Select(i => new MyClass(i));,因此它将为您提供一个新的IEnumerable,其中包含一个新的整数列表.
您可以使用调试器查看此操作.new MyClass(i)在IEnumerable select 的一部分放置一个断点,当你为Console.WriteLine执行它时,你会看到这个部分再次被击中