2

私はLinqPadでこの単純なクエリを試し、2番目のクエリが機能する理由について頭を悩ませましたが、最初のクエリはlist(descen)を変更しません。

  • どうすればそれを機能させることができますか。このコードを使用して、xml属性、値を複製および変更します

失敗する

var doc = XElement.Parse("<Root><Descendants>Welcome</Descendants><Descendants>Stack</Descendants><Descendants>Overflow</Descendants></Root>");
var descen = (from des in doc.Descendants("Descendants") select new XElement(des));
foreach (var desc in descen)
{
    desc.Value += DateTime.UtcNow;
}
descen.Dump();
doc.Dump();

作品

var doc = XElement.Parse("<Root><Descendants>Welcome</Descendants><Descendants>Stack</Descendants><Descendants>Overflow</Descendants></Root>");
var descen = (from des in doc.Descendants("Descendants") select new XElement(des));
foreach (var desc in doc.Descendants("Descendants"))
{
    desc.Value += DateTime.UtcNow;
}
descen.Dump();
doc.Dump();

ストールは私のPC?? WTH

var doc = XElement.Parse("<Root><Descendants>Welcome</Descendants><Descendants>Stack</Descendants><Descendants>Overflow</Descendants></Root>");
var descen = (from des in doc.Descendants("Descendants") select des);
foreach (var desc in descen)
{
    desc.Value += DateTime.UtcNow;
}
var instance = from t in descen select new XElement(t);
doc.Elements("Descendants").LastOrDefault().AddAfterSelf(instance);
descen.Dump();
4

1 に答える 1

4

最初のクエリでdescenは、既存の要素から新しい要素への投影です。それは遅延評価されます-それを繰り返すたびに、それは新しい要素を作成します。

最初のケースでは、を繰り返しdescen、新しい要素を変更します。ただし、これらの変更された要素は、作成後すぐに事実上破棄されます。元のドキュメントの一部ではありません。

2番目のケースでは、元のドキュメントの要素を変更するため、を繰り返すと、変更されたdescen要素のコピーが作成され、それらが表示されます。

編集:元のドキュメントではなくdescen変更したい場合は、の初期化部分の最後に追加するだけです。例えば:ToList()descen

var descen = (from des in doc.Descendants("Descendants")
              select new XElement(des)).ToList();

または、より読みやすいIMO:

var descen = doc.Descendants("Descendants")
                .Select(x => new XElement(x))
                .ToList();

最終的なコードがハングする理由は、AddAfterSelf反復処理instance時に要素が追加されるためです...しかし、これらの要素はドキュメントの一部になります。つまり、descenクエリの一部になります。つまり、クエリの一部になりinstanceます...したがって、反復instanceは完了しません。

于 2012-05-25T09:08:47.987 に答える