2010-05-25 91 views
2

我有一個函數,它檢查對象列表以查看它們是否被點擊並相應地觸發了OnClick事件。我相信該功能正常工作,但我有一個問題:「Collection was modified ...」問題

當我鉤到一個OnClick事件,並刪除並插入元素到列表中的不同位置(此程序的典型功能),我收到「收集已修改...」錯誤。

我相信我明白是怎麼回事:發射必要的onclick事件經過的每個對象

  • 函數週期
  • 觸發一個事件和對象改變的地方以每掛鉤函數
  • 列表
  • 拋出異常的修改集合,而通過它迭代

我的問題是,如何做我允許的功能通過迭代將對象,在適當的時候觸發必要的事件,並仍然允許用戶選擇操縱對象在列表中的位置?

回答

7

有這類的問題,有兩種解決辦法一般:

  • 榜上無名的副本。迭代副本。
  • 列出需要進行的更改。迭代完成後應用更改。

如果您想要將代碼與執行循環的代碼分離開來,那麼「use indices」選項聽起來並不合適。

+0

我認爲第二個選項聽起來最好。我將在更新過程中記錄對列表的任何修改,然後在迭代完成後應用它們。 – 2010-05-25 13:56:00

+0

請注意,當您進行多個編輯 - 「交換1和2」和「交換2和3」或「在A之後移動C」和「刪除」時,您必須清楚「一個」。我通常會發現,通過迭代副本來製作正確的代碼會更容易,儘管它可能非常低效。 – 2010-05-26 11:25:07

2
  • 使用集合的副本而不是初始集合進行迭代。

  • 如果你有一個支持索引的集合(比如List),你可以使用'for'循環而不是'foreach'迭代。

+0

或者,List <> .ForEach() – Alan 2010-05-25 03:21:17

+0

foreach仍然會導致相同的錯誤。 – 2010-05-25 03:21:49

2

如果您使用的是foreach循環操作集合,嘗試用

for (int a = items_count - 1; a >= 0; --a) 
+1

只有當您有索引直接訪問收集項目時,這纔算正常。 – 2010-05-25 03:58:17

2

您所看到的行爲是by design替換它:

的C# 語言的foreach語句(對於Visual Basic中的每個) 隱藏了 枚舉器的複雜性。因此,建議使用foreach 而不是直接操作枚舉器 。

枚舉器可用於讀取集合中的 數據,但它們不能用於修改 基礎集合。

激發同步執行的事件與修改foreach循環中的集合的效果相同。

我的選擇是使用for循環倒退,這樣就避免了更新,具體取決於您是否插入一些循環索引的條件邏輯:

for (var i = collection.Count - 1; i >= 0; i--) { 
    if (condition) 
    collection.Insert(i, item); 
} 

相應遞增的循環將是這個樣子:

for (var i = 0; i < collection.Count; i++) { 
    if (condition) { 
    collection.Insert(i, item); 
    i++; 
    } 
} 
1

集合在迭代時不能被修改。您需要先標記要從集合中刪除的項目,然後將其刪除。根據您的要求,您可以在刪除項目之前或之後觸發事件。此代碼片段顯示我所屬的

List itemsTobeRemoved = new List();對於(var i = 0; i < collection.Count; i ++)if(condition){ itemsTobeRemoved.Add(i); }

的foreach(VAR I =在itemsTobeRemoved 0){ 如果(條件){ collection.RemoveAt(ⅰ); }