簡體   English   中英

C#阻止Collection被修改的異常

[英]C# preventing Collection Was Modified exception

是否

 foreach(T value in new List<T>(oldList) )

當oldList包含1百萬個對象T時危險(代價高昂)?

更常見的是,在枚舉期間添加/刪除元素時,枚舉oldList的最佳方法是什么?

一般規則是,您不應修改您枚舉的同一集合。 如果你想做類似的事情,請保留另一個集合,該集合將跟蹤從原始集合中添加/刪除的元素,然后在退出循環后,對原始集合執行添加/刪除操作。

像這樣

var itemsToBeRemoved = new List<T>();

foreach (T item in myHugeList) 
{
    if (/*<condition>*/)
         itemsToBeRemoved.Add(item);
}

myHugeList.RemoveRange(itemsToBeRemoved);

我通常只為要刪除或添加的所有對象創建一個列表。

foreach我只是將項添加到相應的集合中,並在foreach完成后修改原始集合(循環遍歷removeItemsaddItems集合)

如果您使用Foreach循環來修改集合,那么您將收到如下錯誤。

List<string> li = new List<string>();
    li.Add("bhanu");
    li.Add("test");

    foreach (string s in li)
    {
        li.Remove(s);
    }

解決方案 - 使用For Loop,如下所示。

for (int i = 0; i < li.Count; i++)
    {
        li.RemoveAt(i);
        i--;
    }

如果你的意思是你可以從另一個線程添加/刪除對象,我會:1 - 在添加/刪除線程中同步線程2-,創建要添加或刪除的項目列表3-然后在關鍵項中刪除這些項目部分(所以它很小 - 將項目添加到刪除列表時不必同步)

如果你不想這樣做,你可以使用for而不是foreach,這樣可以避免異常,但你必須格外小心,這樣你就不會得到其他類型的異常

foreach(新列表中的T值(oldList).ToList()) - 試一試

您可以使用標志將修改切換到臨時列表,同時枚舉原始列表。

///你在哪里枚舉

isBeingEnumerated = true
foreach(T value in new List<T>(oldList) )
isBeingEnumerated = false
SyncList(oldList with temporaryList)

///在枚舉時修改的位置

if isBeingEnumerated then
use a temporaryList to make the changes.

它會“慢”但除了在后台線程上運行之外,你無法做更多的事情。 例如,使用BackgroundWorker

如果列表上的操作僅發生在一個線程上,則正確的方法是添加要添加/刪除的項目以分隔列表,並在迭代完成后執行這些操作。

如果你使用多個線程,你將不得不研究多線程編程,例如使用或者更好的ReaderWriterLock

更新:正如另一個Stack Overflow問題中所提到的,現在可以在使用並發集合時在.NET 4.0 中輕松實現

您可以在不使用枚舉器的情況下遍歷列表,所以請執行以下操作:

for(int i = 0;i<oldList.Count;i++) {
   var value = oldList[i];

   ...

   if(itemRemoveCondition) {
     oldList.RemoveAt(i--);
   }
}

對我來說,首先應該考慮使用某種數據分頁,因為擁有這樣的1百萬項大型列表本身就很危險。

你聽說過工作單元模式嗎?

您可以實現它,以便標記對象以進行創建,更新或刪除,之后,您可以調用“SaveChanges”,“Commit”或任何其他執行“應用更改”的工作,您將完成。

例如,您遍歷可枚舉(oldList)並將其標記為“delete”。 稍后,您調用“SaveChanges”,更抽象,通用的工作單元將遍歷要處理的小的,已過濾的對象列表。

無論如何,避免列出百萬件物品。 您應該使用分頁的對象列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM