2010-04-27 60 views
3

什麼是在我的XDocument中通過一組XElement手動迭代(即,一次一個「下一個」按鈕)的「最佳實踐」方式?說我選擇的元素集合我想正是如此:手動迭代XML元素(C#,XDocument)

var elems = from XElement el in m_xDoc.Descendants() 
      where (el.Name.LocalName.ToString() == "q_a") 
      select el; 

我可以用一個IEnumerator遍歷它們,即 的IEnumerator m_iter;

但是,當我到最後,如果我打電話Reset(),它會引發一個NotSupportedException。這是因爲,正如第22章「迭代器」中的Microsoft C#2.0規範所述「請注意,枚舉器對象不支持IEnumerator.Reset方法。調用此方法會導致拋出System.NotSupportedException異常。」

那麼這樣做的正確方法是什麼?如果我也想要雙向迭代,也就是「後退」按鈕怎麼辦?

有人在微軟討論論壇上說過我不應該直接使用IEnumerable。他說有一種方法可以用我想要的LINQ做什麼,但我不明白是什麼。其他人建議將XElements轉儲到帶有ToList()的列表中,我認爲這可行,但我不確定這是否是「最佳實踐」。在此先感謝您的任何建議!

回答

1

解決方案非常簡單。只需從XElements集合中創建一個List。

var elems = (from XElement el in m_xDoc.Descendants() 
      where (el.Name.LocalName.ToString() == "q_a") 
      select el).ToList(); 

你可以通過索引器elems[i]來枚舉並來回跳轉。只需將當前索引存儲在一個變量中,然後通過單擊按鈕(使用換行)對其進行遞減/遞增。

您的xml根據您的linq查詢的需求進行解析(請參閱deferred execution and lazy evaluation in Linq to XML的MSDN)。即使它支持IEnumerable.Reset(),它也不得不每次都解析它。如果您致電.ToList<T>(),它會解析所有後代元素並將其加載到內存中。

1

這是很少需要直接使用枚舉器;只需在elems上使用foreach即可。這裏的迭代兩次:

// first time 
foreach(var item in elems) {...} 
// second time 
foreach(var item in elems) {...} 

無需Reset() - 它只是使用GetEnumerator()你兩次,這是做它的正確途徑。如果無論出於何種原因無法運行查詢兩次,或者需要隨機訪問而不是順序訪問,那麼您必須將其緩存 - 可能是ToList()

+0

我想'foreach'循環不是什麼操作正在尋找。只有當用戶按下按鈕時,他纔想獲得下一個元素。我認爲他最好將數據存儲到列表中。 – 2010-04-27 21:53:05