2

我在 LinqPad 上尝试了这个简单的查询,并对为什么第二个查询有效但第一个查询没有改变列表(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();

摊位是我的电脑??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并随时修改新元素。但是,这些修改过的元素在创建后很快就被有效地丢弃了——它们不是原始文档的一部分。

在第二种情况下,您修改了原始文档中的元素,因此当您迭代时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 回答