IEnumerable 与 List 上的 C# foreach - 元素修改仅对数组持久 - 为什么?

标签 c# foreach reference ienumerable

在 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/

相关文章:

c# - 允许搜索重音字符吗?

c# - 有没有办法在没有数据源的情况下将 LINQ 查询创建为变量(尚未)?

C# - 从 C# WinForm 应用程序运行/执行 "Excel to CSV File Converter"控制台应用程序

java - 有没有一种简单的方法可以在java中并行化foreach循环?

c++ - 使用模板将数组作为引用作为参数传递

c# - 在 WebApi 中使用 Autofac 进行 Hangfire

PHP/MySQL - 停止 Foreach 运行相同的查询

php - 数组内的foreach循环

c - C中的 "undefined reference to varName"是什么意思?

c++ - 为什么我不能返回对压缩字段的引用?