我在LinqPad上尝试了这个简单的查询,并为第二个查询为什么起作用而but之以鼻,但第一个查询并没有改变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();


停转我的电脑? 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();

最佳答案

在第一个查询中,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永远不会完成。

09-20 01:25