Linq 重新评估的问题,跳过内容
现在我不太确定这里的问题是什么,但似乎每次迭代都会重新评估 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()
方法,但随后我必须稍微更改一些其他代码。这并不是一个真正的问题,我只是希望它像这样工作,并且也了解这里发生了什么。
Now I'm not really sure what the problem here is but it seems that Linq queries are re-evaluated each iteration which is a effect I want here. However for some reason he skips elements he shouldn't when he does so.
Can someone help me understand what's going on here. Here is the Linq-to-XML code:
var contents = (from sdt in document.MainDocumentPart.RootElement.Descendants<SdtElement>()
select sdt);
foreach (SdtElement item in contents)
{
ReplaceContent(item, data);
}
The ReplaceContent
method rips a part of the SdtElement
out and puts it instead of that element. Next iteration contents has 1 less element as expected. However when I hit one paragraph (so 2 elements under the same parent) with 2 SdtElements and after he replaces the first one he doesn't include the second one and skips it. It's still in the document though.
Here is a part of the ReplaceContent
method:
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);
}
}
I could use the ToList()
method on the Linq but then I'd had to change some other code a little. That's not really a problem I just rather would want it to work like this and also understand what it is that's going on here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
LINQ 查询在每次使用时都会重新评估,因为这使得它们占用的内存最少(通常为 O(1) 内存使用),并且可以快速返回第一个结果。
在那些不是问题的情况下,这是迄今为止最好的方法。
在出现问题的情况下,请使用 toList() 或类似方法来解决。
中间立场是构建一个可枚举的对象,它传递结果以供立即处理,但它也维护一个用于后续工作的列表。如果第一次传递可能导致下一个操作因不必要而被放弃,那么这可能特别有用。
LINQ queries get re-evaluated on each use because this allows them to be minimal in memory (generally O(1) memory use) and fast to return the first result.
In those cases where it's not a problem, it's by far the best way to go.
In those cases where it is a problem, use toList() or similar to get by.
A middle ground is to build an enumerable which passes through results for immediate processing, but which also maintains a list for subsequent work. This can be particularly useful if the first pass-through may result in the next operations being abandoned as unnecessary.