[英]System.InvalidOperationException: Collection was modified
[英]Best practice to avoid InvalidOperationException: Collection was modified?
我經常需要這樣的東西:
foreach (Line line in lines)
{
if (line.FullfilsCertainConditions())
{
lines.Remove(line)
}
}
這是行不通的,因為由於在循環期間更改了枚舉數,所以我總是收到InvalidOperationException
。
因此,我將所有此類循環更改為以下內容:
List<Line> remove = new List<Line>();
foreach (Line line in lines)
{
if (line.FullfilsCertainConditions())
{
remove.Add(line)
}
}
foreach (Line line in remove) {
{
lines.Remove(line);
}
我不確定這是否是最好的方法,因為在最壞的情況下,我必須對原始列表進行2次迭代,因此它需要2n而不是n的時間。
有一個更好的方法嗎?
編輯:
我可以使用Mark的答案來做到這一點!但是,如果我的集合沒有實現RemoveAll()怎么辦?
例如一個
System.Windows.Controls.UIElementCollection
編輯2:
再次在Mark的幫助下,我現在可以進行以下調用以刪除所有ScatterViewItem:
CollectionUtils.RemoveAll(manager.getWindow().IconDisplay.Items, elem => elem.GetType() == typeof(ScatterViewItem));
將其直接烘焙到List<T>
:
lines.RemoveAll(line => line.FullfilsCertainConditions());
或在C#2.0中:
lines.RemoveAll(delegate(Line line) {
return line.FullfilsCertainConditions();
});
在非List<T>
情況下(您對問題的編輯),您可以像下面這樣包裝(未經測試):
static class CollectionUtils
{
public static void RemoveAll<T>(IList<T> list, Predicate<T> predicate)
{
int count = list.Count;
while (count-- > 0)
{
if (predicate(list[count])) list.RemoveAt(count);
}
}
public static void RemoveAll(IList list, Predicate<object> predicate)
{
int count = list.Count;
while (count-- > 0)
{
if (predicate(list[count])) list.RemoveAt(count);
}
}
}
由於UIElementCollection
實現了(非通用的) IList
因此應該可以使用。 而且非常方便,使用C#3.0,您可以在IList
/ IList<T>
之前添加一個this
,並將其作為擴展方法。 唯一的妙處是,匿名方法的參數將是object
,因此您需要將其拋棄。
您只需將原始列表替換為過濾后的列表即可:
lines = lines.Where(line => line.FullfilsCertainConditions()).ToList();
建立新的清單:
public IList<Line> GetListWithoutFullfilsCertainConditions(IList<Line> fullList)
{
IList<Line> resultList = new List<Line>(fullList.Count);
foreach (Line line in fullList)
{
if (!line.FullfilsCertainConditions())
{
resultList.Add(line)
}
}
return resultList;
}
您也可以只使用while循環。
int i = 0;
while(i < lines.Count)
{
if (lines[i].FullfilsCertainConditions())
{
lines.RemoveAt(i);
}
else {i++;}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.