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.
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.