2010-08-16 52 views
1

現在我不確定這裏的問題是什麼,但似乎Linq查詢重新評估每次迭代這是我想要的效果。然而由於某種原因,他跳過他不應該這樣做的元素。Linq重新評估的問題,跳過內容

有人能幫我理解這裏發生了什麼。這裏是LINQ到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()方法,但隨後我不得不改變一些其他的代碼一點。這不是一個真正的問題,我只是希望它能像這樣工作,並且明白這是怎麼回事。

回答

3

LINQ查詢會在每次使用時得到重新評估,因爲這可以使它們在內存中最小化(通常使用O(1)內存)並快速返回第一個結果。

在那些沒有問題的情況下,這是迄今爲止最好的選擇。

在出現問題的情況下,使用toList()或類似的方法來獲取。

一箇中間立場是建立一個枚舉,它通過結果立即處理,但它也爲後續工作維護一個列表。如果第一次通過可能導致下一次操作被放棄,這可能特別有用,因爲這是不必要的。

+0

感謝您的信息。你知道他爲什麼會忽略重新評估中的特定元素嗎?在這種情況下,他將任何具有與之前更改的迭代相同的父代作爲參數。 – 2010-08-16 12:37:28

+0

哦,你可以用一個簡短的例子來解釋一下這個令人激動的方法嗎? – 2010-08-16 12:38:10

+0

據我所見,你正在改變迭代之間的來源,雖然我可能是錯誤的。如果是這樣,這將解釋每次迭代的變化。至於可枚舉的方法,您需要構建一個包裝枚舉器的類,並在其自己的枚舉器中從內部存儲返回,或者如果存儲耗盡,則從包裝的枚舉器獲取並在返回之前將其放入內部存儲。我認爲這不會有用,但在某些情況下可能會有用。 – 2010-08-16 12:48:07