【问题标题】:Issues with Linq re-evaluation, skips contentLinq 重新评估的问题,跳过内容
【发布时间】:2010-08-16 11:53:09
【问题描述】:

现在我不确定这里的问题是什么,但似乎每次迭代都会重新评估 Linq 查询,这是我想要的效果。但是由于某种原因,他跳过了他不应该这样做的元素。

谁能帮我理解这里发生了什么。这是 Linq-to-XML 代码:

var contents = (from sdt in document.MainDocumentPart.RootElement.Descendants<SdtElement>()
                select sdt);

foreach (SdtElement item in contents)
{
    ReplaceContent(item, data);
}

ReplaceContent 方法将SdtElement 的一部分取出并放置它而不是那个元素。下一次迭代内容与预期的一样少了 1 个元素。但是,当我用 2 个 SdtElements 击中一个段落(因此同一父级下的 2 个元素)并且在他替换第一个段落之后,他不包括第二个段落并跳过它。但它仍在文档中。

这是ReplaceContent方法的一部分:

public void ReplaceContent(SdtElement contentControl, XElement xml)
{
    OpenXmlElement content = null;

    if (contentControl is SdtRun)
    {
        content = (contentControl as SdtRun).SdtContentRun.GetFirstChild<Run>();
        //Items cut for brevity
    }

    //Items cut for brevity
    if (content != null)
    {
         content.Remove();
         var parent = contentControl.Parent;
         parent.ReplaceChild(content, contentControl);
    }
}

我可以在 Linq 上使用ToList() 方法,但是我不得不稍微更改一些其他代码。这不是一个真正的问题,我只是希望它像这样工作,并了解这里发生了什么。

【问题讨论】:

    标签: c# linq foreach openxml


    【解决方案1】:

    LINQ 查询在每次使用时都会被重新评估,因为这使得它们在内存中的使用量最少(通常为 O(1) 内存使用)并且可以快速返回第一个结果。

    在没有问题的情况下,这是迄今为止最好的方法。

    如果出现问题,请使用 toList() 或类似方法解决问题。

    中间立场是构建一个可枚举的,它通过结果进行立即处理,但它也为后续工作维护一个列表。如果第一次传递可能导致下一个操作因不必要而被放弃,这将特别有用。

    【讨论】:

    • 感谢您的信息。你知道他为什么会在重新评估时忽略特定的元素吗?在这种情况下,他会忽略与之前更改的迭代具有相同父级的任何内容。
    • 哦,你能用一个简短的例子来解释一下这个可枚举的方法吗?
    • 据我所知,您正在更改迭代之间的源,尽管我可能错了。如果是这样,那将解释每次迭代的变化。至于可枚举的方法,您需要构建一个包装枚举器的类,并在其自己的枚举器中从内部存储返回,或者,如果存储已用尽,则从包装的枚举器中获取并将其放入内部存储中,然后再返回它。我不认为它在这里有用,但在某些情况下可能有用。
    • 你是对的,我正在更改来源。然而,它们是一些仍然满足原始查询的元素,它们被忽略并跳过,而其他元素则没有。这是正常行为吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    • 1970-01-01
    • 2011-09-11
    • 2017-03-25
    • 2011-05-06
    • 2013-11-04
    相关资源
    最近更新 更多