c# - 使用 'ReplaceWith' 迭代 XElement 集合仅在我首先使用 'ToList()' 时有效

标签 c# linq-to-xml iteration

此代码有效:

var element = XElement.Parse("<div><span><em>Content</em></span><span><em>Content2</em></span></div>");

var spans = element.Descendants("span").ToList();

foreach(var span in spans)
{
    span.ReplaceWith(span.Nodes());
}

这不会,给出错误“对象引用未设置到对象的实例。”:

var element = XElement.Parse("<div><span><em>Content</em></span><span><em>Content2</em></span></div>");

var spans = element.Descendants("span");

foreach(var span in spans)
{
    span.ReplaceWith(span.Nodes());
}

唯一的区别是我在创建后代节点列表时删除了“ToList()”。这是为什么?

IQueryable 实现了 IEnumerable,我认为迭代强制延迟执行,那么为什么“ToList()”在这里有所作为?

最佳答案

在第二种情况下,您在迭代集合 spans 时更改了它,因此发生了不好的事情。也许它试图给你它记得的下一个 span ,但你已经删除了它。

(在像列表这样的核心集合中,您会得到一个异常,明确指出该集合已被修改。例如,在 List<.> 中,每次修改列表时都会更改版本号;当您在列表上调用 ToNext枚举器,如果版本发生变化,则抛出异常。

在 LINQ-to-XML 中,开发人员似乎没有添加这种行为。)

在第一种情况下,当您修改原始树时,由 ToList 创建的列表不会被修改。

我会尝试这样的事情:

XElement span = null; // or whatever class this should be
while ((span = element.Descendants("span").FirstOrDefault()) != null)
    span.ReplaceWith(span.Nodes());

即一个接一个地替换 span,而不是试图一次把它们都弄好然后替换它们。

关于c# - 使用 'ReplaceWith' 迭代 XElement 集合仅在我首先使用 'ToList()' 时有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13049078/

相关文章:

c# - 调试 .net 的 WebClient

c# - 用 MahApps.Metro 无边框窗口的菜单替换窗口标题

c# - DateTime.TryParse API 关于日期元素分隔符或定界符的内部行为

c# - 在 C# 中从文件中获取不同节点值的快速方法?

ios - 如果我们使用dispatch_apply,如何打破循环?

c# - 具有 protected setter 的最小起订量属性

c# - linq 到 xml : read a xml config file

.net - 多个后代类型 linq

javascript - 迭代未知复杂度的复杂 JSON 对象

Lua 表和迭代