C#克隆XML节点时foreach出现无限循环的原因及解决方法
问题原因与解决办法
为什么会无限循环?
XmlNodeList是动态延迟求值的集合,它不会一次性把匹配的节点全部提取出来存成固定列表。每次你访问它的元素(比如foreach迭代时),都会重新执行一遍对应的XPath查询。
你在循环里不断往<offers>节点下添加新的<offer>克隆节点,每次迭代的XPath查询都会把刚加的新节点也包含进来,相当于循环的“遍历目标”一直在变多,自然就陷入无限循环了。
为什么断点跟踪时结果正常?
当你在调试时查看listOffers变量,调试器会强制遍历整个XmlNodeList,把所有匹配的节点一次性加载到内存里,相当于把动态集合变成了静态的快照。后续循环再访问时,就只会用这个快照里的原始节点,不会再触发新的XPath查询,所以能正常结束循环。
解决办法
有两种简单的处理方式:
方式一:转成静态集合
把动态的XmlNodeList转换成静态的List<XmlNode>,这样后续添加新节点不会影响遍历的集合:
// 需要引用System.Linq命名空间 var listOffers = xDoc.SelectNodes("//offers/offer").Cast<XmlNode>().ToList(); foreach (XmlNode offer in listOffers) { XmlNode clone = offer.Clone(); offers.AppendChild(clone); Console.WriteLine("Create clone"); }
方式二:基于原始节点数量遍历
先获取初始的节点总数,用for循环遍历原始数量的节点,避开动态集合的影响:
XmlNodeList listOffers = xDoc.SelectNodes("//offers/offer"); int originalOfferCount = listOffers.Count; // 先存下初始节点数 for (int i = 0; i < originalOfferCount; i++) { XmlNode offer = listOffers[i]; XmlNode clone = offer.Clone(); offers.AppendChild(clone); Console.WriteLine("Create clone"); }
内容的提问来源于stack exchange,提问作者Xmel25
相关产品推荐
相关产品推荐

