我在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
永远不会完成。