我非常惊讶地发现今天有以下行为:给定一个类
class Foo
{
prop int FooNumber { get; set; }
}
和此代码
IEnumerable<Foo> foos = Enumerable.Range(0,3).Select(new Foo());
foreach (var foo in foos)
foo.Bar = 5;
foreach (var foo in foos)
Console.Write(foo.Bar); // Writes 000
将foos
初始化为new List<Foo>{ new Foo(), new Foo(), new Foo() }
时,会使循环写入“555”。
我的问题:为什么会发生这种情况,有没有办法绕过这个不使用.ToList()
(需要评论,因为这里似乎不需要)。
答案 0 :(得分:20)
这是因为foos
每次枚举时都会动态生成。因此,在第一次迭代期间,您将在迭代结束后不再被任何引用的对象上设置属性值。第二次迭代适用于具有默认属性值的新构造的对象。
将foos
初始化为“持久性”对象列表会改变一些事情,就像使用.ToList()
出于同样的原因一样(构造“固定”列表并迭代两次;原始动态生成{ {1}}只迭代一次。)
确定你应该在这里使用IEnumerable
:一般来说我不觉得需要评论,因为不习惯多次迭代动态生成的序列(I相信许多代码分析工具都会对此提出警告),但无论如何都要写一个。
答案 1 :(得分:3)
似乎很明显发生了什么:每次枚举时,都会实例化新的Foo对象。
如果你想保留属性值(Foo.Bar
),那么你将不得不将Foo的保留在某处,并且ToList()是一种简单的做法此