【发布时间】:2013-03-28 12:09:10
【问题描述】:
我有以下 XML。
<Parts>
<Part name="Part1" disabled="true"></Part>
<Part name="Part2" disabled="false"></Part>
<Part name="Part3" ></Part>
<Part name="Part4" disabled="true"></Part>
</Parts>
我想删除disabled 属性设置为true 的节点。如果任何 'Part' 元素都没有使用 'disabled' 属性,则表示它没有被禁用。
我写了以下代码:
XmlNode root = xmlDoc.DocumentElement;
List<XmlNode> disabledNodes = new List<XmlNode>();
foreach(XmlNode node in root.ChildNodes)
{
if(node.Attributes["disabled"] != null &&
Convert.ToBoolean(node.Attributes["disabled"].Value))
{
disabledNodes.Add(node);
}
}
foreach (XmlNode node in disabledNodes)
{
root .RemoveChild(node);
}
此代码按预期从 XML 中删除 2 个节点。
然后我编写了以下代码以使代码紧凑:
foreach (XmlNode node in root.ChildNodes.Cast<XmlNode>()
.Where(child => child.Attributes["disabled"] != null &&
Convert.ToBoolean(child.Attributes["disabled"].Value)))
{
root.RemoveChild(node); // This line works fine without any exception.
}
我发现这个循环只迭代了一次,从 XML 中只删除了一个节点。
编辑问题:
现在当我更改foreach 循环时,这次我使用ToList() 方法将LINQ 表达式的结果转换为List<T>(正如@Toni Petrina 在他的回答中所建议的那样)。这一次效果很好!
foreach (XmlNode node in root.ChildNodes.Cast<XmlNode>()
.Where(child => child.Attributes["disabled"] != null &&
Convert.ToBoolean(child.Attributes["disabled"].Value)).ToList())
{
root.RemoveChild(node); // This line works fine without any exception.
}
为什么使用ToList() 使LINQ 表达式在foreach 循环中按预期工作? LINQ 结果在两种不同情况下表现不同的任何技术原因?
我正在使用 .NET 4.0。
【问题讨论】:
-
我认为问题在于您正在迭代“root”,同时尝试从中删除一些 foreach 循环不允许的内容
-
@CSharpLearner 从
foreach的正文中删除RemoveChild()代码,看看它迭代了多少次? -
我在这里尝试了这段代码:ideone.com/7gyQfj 并得到了我们期望的错误(但你不是)。有趣的是,我在 VSExpress 2012 上进行了尝试,它按预期工作(删除了所有预期的节点)。
-
不再是同一个查询。当您从 LINQ 迭代一个集合时,您一次请求一个项目。并且您更改了从中提取项目的集合。如果您不修改集合,它会正常工作。请记住:在迭代集合时不要更改集合。
-
我已经发布了一个关于为什么在某些情况下您看不到异常的问题。 stackoverflow.com/questions/15682613/…
标签: c# .net linq linq-to-xml