10

たとえば、LINQ ステートメントで新しいオブジェクトを作成する場合:

var list = new List<string>() { "a", "b", "c" };
var created = from i in list select new A();

クラスAは次のようになります。

class A
{
    public string Label;
}

次に、 foreach ループを使用して A のプロパティを変更します。

foreach (var c in created) {
    c.Label = "Set";
}

IEnumerable後でオブジェクトにアクセスするときに値が設定されないのはなぜですか。たとえば、次のアサーションは失敗します。

Assert.AreEqual("Set", created.ElementAt(2).Label);

なぜこれが起こるのだろうか。foreach ステートメントがクエリを実行し、オブジェクトの作成をトリガーすることを期待します。MSDN のドキュメントには、「クエリ変数が foreach または For Each ループで繰り返されるまで、クエリの実行が延期される」と記載されています。

.NET 4.5 と Mono 3.2.0 でこの動作を再現しました。作成されたオブジェクトにアクセスする前にを呼び出すToListと、この問題はなくなります。IEnumerable

4

1 に答える 1

6

created結果ではなくクエリであるため、発生しています。したがって、それを列挙するたびに、Select最初からやり直しを評価しています。

これを機能させたい場合は、クエリを表すcreatedだけでなく、実際のリストを作成してください。IEnumerable

たとえば、次を追加します。

created = created.ToList();

あなたは言う:

foreach-statement がクエリを実行し、オブジェクトの作成をトリガーすることを期待します

これはまさに起こっていることです。created問題は、最初だけでなく、を反復処理するたびにオブジェクトの作成が行われることです。ElementAt()メソッドは を反復処理するため、created新しいAを再度作成するだけです。

于 2013-09-20T12:49:03.640 に答える