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これは、列挙するたびに動的に生成されるために発生します。したがって、最初の反復中に、反復の終了後に参照されなくなったオブジェクトのプロパティ値を設定しています。2 番目の反復は、デフォルトのプロパティ値を持つ新しく構築されたオブジェクトに対して機能します。

同じ理由でfoosusing と同様に、「永続的な」オブジェクトのリストに初期化すると状況が変わります (「固定された」リストは構築され、2 回反復されます。元の動的に生成されたリストは1 回だけ反復されます)。.ToList()IEnumerable

.ToList()ここで使用する必要があることを確認しました。一般に、動的に生成されたシーケンスを複数回反復することは慣習的ではないため、コメントは必要ないと思います (多くのコード分析ツールがこれに対して警告していると思います)。 1つ書いてください。

于 2012-07-10T10:16:57.803 に答える
3

何が起こっているかは明らかです。列挙するたびに、新しい Foo オブジェクトをインスタンス化しています。

プロパティ値 ( Foo.Bar) を保持したい場合は、Foo のどこかを保持する必要があります。ToList() はこれを行う簡単な方法です。

于 2012-07-10T10:18:50.723 に答える