10

今天我非常惊讶地观察到以下行为:给定一个类

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

初始化foosnew List<Foo>{ new Foo(), new Foo(), new Foo() }使循环写入“555”。

我的问题:为什么会发生这种情况,有没有办法在不使用的情况下规避这种情况.ToList()(需要评论,因为这里似乎不需要它)。

4

2 回答 2

20

发生这种情况是因为foos每次枚举它时都会动态生成。因此,在第一次迭代期间,您将在迭代结束后不再被任何对象引用的对象上设置属性值。第二次迭代适用于具有默认属性值的新构建的对象。

初始化foos到“持久”对象列表会改变事情,使用.ToList()也是出于同样的原因(构建“固定”列表并迭代两次;原始动态生成IEnumerable的列表仅迭代一次)。

确定你应该.ToList()在这里使用:一般来说,我觉得它不需要评论,因为不习惯多次迭代动态生成的序列(我相信许多代码分析工具都会警告这一点),但无论如何都要这样做写一个。

于 2012-07-10T10:16:57.803 回答
3

发生的事情似乎很明显:每次枚举时,您都在实例化新的 Foo 对象。

如果您希望保留属性值 ( Foo.Bar),那么您将不得不将 Foo 保留在某处,而 ToList() 是一种简单的方法。

于 2012-07-10T10:18:50.723 回答