C#foreach on IEnumerable vs. List – 元素修改仅对数组持久 – 为什么?
在C#中,我注意到如果我在LINQ生成的IEnumerable
集合上运行foreach循环并尝试修改每个T元素的内容,那么我的修改不会持久。
另一方面,如果在创建集合时应用ToArray()
或ToList()
方法,则对foreach循环中各个元素的修改是持久的。
我怀疑这在某种程度上与延迟执行有关,但究竟对我来说并不完全是显而易见的。 我真的很感激这种行为差异的解释。
这是一些示例代码 – 我有一个带有构造函数和自动实现属性的类MyClass
:
public class MyClass { public MyClass(int val) { Str = val.ToString(); } public string Str { get; set; } }
在我的示例应用程序中,我使用LINQ Select()
通过最终应用ToList()
方法,基于整数集合创建两个MyClass
对象集合,一个IEnumerable
和一个IList
。
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时都会创建一个新的MyClass实例。 通过调用ToList或ToArray,然后创建一个List或Array,并使用从IEnumerable的迭代创建的新MyClass实例填充它。
上述就是C#学习教程:C#foreach on IEnumerable vs. List – 元素修改仅对数组持久 – 为什么?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/987259.html