【问题标题】:why does i.Parent.ReplaceWith(i) not throw an exception?为什么 i.Parent.ReplaceWith(i) 不抛出异常?
【发布时间】:2017-02-16 09:04:07
【问题描述】:

在这些语句中(使用MoreLinq 运行):

var xml = @"
<div>
<p>
    <h2>hey</h2>
</p>
<pre />
<h2 class=""cool"" />
<p>
    <h2>okay</h2>
</p>
</div>
".Trim();

var div = XElement.Parse(xml);
var h2Elements = div.Descendants("h2");
h2Elements.ToList().ForEach(i =>
{
    if(i.Parent.Name != "p") return;
    i.Parent.ReplaceWith(i);
});

我看到i.Parent.ReplaceWith(i) 不会引发异常,但这会引发空引用异常(使用来自MoreLinqForEach):

h2Elements.ForEach(i =>
{
    if(i.Parent.Name != "p") return;
    i.Parent.ReplaceWith(i);
});

我知道 LINQ 的 ToList() 正在制作列表的副本,但该副本不会也抛出异常吗?另外,这里是否发生了某种孤立引用的内存泄漏?

【问题讨论】:

    标签: c# linq-to-xml morelinq


    【解决方案1】:

    您根本不需要 MoreLINQ 来演示这一点 - 您也可以简化示例代码:

    using System;
    using System.Linq;
    using System.Xml.Linq;
    
    class Program
    {    
        static void Main()
        {
            var element = new XElement(
                "root",
                new XElement("parent", new XElement("child")),
                new XElement("parent", new XElement("child"))
            );
            var children = element.Descendants("child");
            foreach (var child in children.ToList())
            {
                child.Parent.ReplaceWith(child);
            }
        }
    }
    

    如果没有ToList 调用,则会抛出NullReferenceException。使用ToList() 电话,也不例外。例外是:

    Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
       at System.Xml.Linq.XContainer.<GetDescendants>d__39.MoveNext()
       at Program.Main()
    

    基本上,您通过在迭代树时修改树来使查询无效。这有点像在迭代 List&lt;T&gt; 时调用 AddRemove,但 LINQ to XML 更难发现问题并引发有意义的异常。请务必注意,调用 ReplaceWith 时不会出现异常 - 这是 iteration 部分失败,因为在您修改它后它无法正确找到遍历树。

    当您调用 ToList() 时,您只是在列表中获得单独的 XElement 值 - 当您遍历该列表时,对元素的任何更改都不会更改列表中出现的引用。

    至于内存泄漏:不,这就是垃圾收集器的用途......

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 2017-08-22
      • 2023-04-10
      • 2014-07-09
      • 2017-07-03
      • 1970-01-01
      • 2011-01-04
      相关资源
      最近更新 更多