2010-01-04 45 views
2

當枚舉一個.NET集合,MSDN states是:枚舉集合,然後修改它,引發異常的先例是什麼?

的枚舉仍然有效,只要集合保持不變。如果對集合進行更改(如添加,修改或刪除元素),則枚舉器將無法恢復無效,並且其行爲未定義。

「無法恢復無效」是什麼意思?

以一個二叉樹爲例,引用都是向左和向右的子元素,也是父元素。在這樣的樹中,對樹中單個節點的單引用足以在樹中導航,因爲您可以輕鬆地從中找到樹中的下一個節點。因此,對於那棵樹,假設我刪除了一些其他節點(假設我沒有移除我當前正在坐的節點),我是否應該仍然使枚舉器無效?請注意,我不是在說這裏的多線程操作,只是一個運行循環的線程,並修改了循環體內的集合。

難道這個「法律」真的是一個法則嗎,即使普查員可能繼續,它應該不會?

回答

8

難道這個「法律」真的是一個法則嗎?即使這個普查員可以繼續下去,也不應該這樣?

就我個人而言,我認爲即使理論上可以繼續下去,讓您的調查員投擲也是一種很好的做法。

通常,人們不經意地將代碼改變爲foreach循環中的集合。如果不這樣做,它可能不會投入開發人員當前正在測試的特定實例,但是不同的運行時條件可能很容易使其丟失。

通過總是拋出,你迫使開發人員把你的代碼與框架的集合和枚舉一樣對待,我認爲這是一件好事,因爲它在處理庫時降低了驚喜程度。

+2

+1。我認爲,以一致的方式拋出異常的安全性遠遠超過了能夠繼續枚舉已被修改的集合的潛在好處,這種集合的調整方式不會影響統計員,而取決於其位置。 – 2010-01-04 18:42:40

+0

這就是我的想法 - 一致性(特別是框架)的價值比在邊緣情況下能夠做到這一點的邊際價值更高。 – 2010-01-04 18:51:26

2

標準收集器的實現使得它成爲一個法則。當它們被創建時,它會從集合對象中複製一個私有的「版本」整數。修改版本的收集增量。迭代器方法比較版本和引發不匹配的時間。沒辦法解決這個問題。

但是,有一個集合類允許在枚舉時修改集合:Microsoft.VisualBasic.Collection。它需要這樣做才能保持與VB6 Collection類的兼容。你可能想看看它是如何完成的。 IIRC,它會在所有迭代器上保留一個WeakReference,然後在集合被修改時更新迭代器。這當然不是很簡單,刪除一個元素並重新添加它可以枚舉兩次相同的對象。它也不便宜。

相關問題