gpt4 book ai didi

c# - Linq、XmlNodes、foreach 和异常

转载 作者:太空狗 更新时间:2023-10-29 17:56:20 24 4
gpt4 key购买 nike

考虑以下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();

xmlDoc.LoadXml(@"<Parts>
<Part name=""DisappearsOk"" disabled=""true""></Part>
<Part name=""KeepMe"" disabled=""false""></Part>
<Part name=""KeepMe2"" ></Part>
<Part name=""ShouldBeGone"" disabled=""true""></Part>
</Parts>");

XmlNode root = xmlDoc.DocumentElement;
List<XmlNode> disabledNodes = new List<XmlNode>();

try
{

foreach (XmlNode node in root.ChildNodes.Cast<XmlNode>()
.Where(child => child.Attributes["disabled"] != null &&
Convert.ToBoolean(child.Attributes["disabled"].Value)))
{
Console.WriteLine("Removing:");
Console.WriteLine(XDocument.Parse(node.OuterXml).ToString());
root.RemoveChild(node);
}
}
catch (Exception Ex)
{
Console.WriteLine("Exception, as expected");
}

Console.WriteLine();
Console.WriteLine(XDocument.Parse(root.OuterXml).ToString());

Console.ReadKey();
}
}
}

当我在 visual studio express 2010 中运行此代码时,我没有像预期的那样出现异常。我希望有一个,因为我在迭代时从列表中删除了一些东西。

我得到的是一个只删除了第一个子节点的列表:

enter image description here

为什么我没有得到无效操作异常?

请注意,IDEOne.com 中的等效代码确实给出了预期的异常:http://ideone.com/qoRBbb

另请注意,如果我删除所有 LINQ (.Cast().Where()),我会得到相同的结果,仅删除一个节点,无一异常(exception)。

我在 VSExpress 中的设置有问题吗?


请注意,我知道涉及延迟执行,但我希望 where 子句在迭代时迭代源枚举(子注释),这会给出我期望的异常。

我的问题是,我在 VSexpress 中没有得到该异常,但在 IDEOne 中得到了(我希望在两种/所有情况下都会出现这种情况,或者至少如果没有,我希望得到正确的结果)。


来自 Wouter's answer当第一个 child 被删除时,它似乎使迭代器无效,而不是给出异常。官方有没有这样说的?在其他情况下是否会出现这种行为?我会调用静默地使迭代器无效而不是异常“沉默但致命”。

最佳答案

即使是下面的代码也不会抛出任何异常:

foreach (XmlNode node in root.ChildNodes)
root.RemoveChild(node);

它只会删除一个元素。我不是 100% 我的解释是正确的,但它是在正确的轨道上。当您迭代一个集合时,您会检索它的枚举器。对于作为集合的 XmlNode,这是一个名为 XmlChildEnumerator 的自定义类。

如果您通过 Reflector 查找 MoveNext 实现,您会看到枚举器记住它当前正在查看的节点。当您调用 MoveNext 时,您将移动到下一个同级。

上面代码中发生的事情是您从集合中获取第一个节点。在 foreach 循环主体中隐式生成的枚举器将第一个节点作为其当前节点。然后,在 foreach 循环的主体中删除该节点。

现在该节点已从列表中分离出来,执行将再次调用 MoveNext。但是,由于我们刚刚从集合中删除了第一个节点,因此它与集合分离并且节点没有兄弟节点。由于该节点没有兄弟节点,迭代停止并退出 foreach 循环,因此仅删除单个元素。

这不会抛出异常,因为它不检查集合是否已更改,它只是想移动到它可以找到的下一个节点。但是由于移除(分离)的节点不属于集合,因此循环停止。

希望这能解决问题。

关于c# - Linq、XmlNodes、foreach 和异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15682613/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com