我的问题是枚举器从SortedList中删除项目是否安全?
SortedList<decimal, string> myDictionary;
// omitted code
IEnumerator<decimal, string> enum = myDictionary.GetEnumerator();
while(enum.MoveNext)
{
// is it ok to remove here?
myDictionary.Remove(enum.Current.Key);
}
答案 0 :(得分:8)
这将抛出异常 - 您无法在迭代时修改集合。
如果你仔细想一想,你会理解为什么。如果允许在集合中添加或删除,则不再迭代同一集合 - 您要么太多(添加),要么没有足够的项目(删除)。
答案 1 :(得分:4)
如前所述,你不想做什么。但是,另一种解决方案是简单地维护标记为删除的项目列表,然后删除这些后续词。我也会选择foreach
而不是while
循环,例如。
var removeList = new List<decimal>();
foreach (var item in myDictionary)
{
// have a condition which indicates which items are to be removed
if (item.Key > 1)
{
removeList.Add(item.Key);
}
}
或者,如果您只是尝试检索要删除的项目,请使用LINQ
var removeList = myDictionary.Where(pair => pair.Key > 1).Select(k => k.Key).ToList();
然后从列表中删除它们。
// remove from the main collection
foreach (var key in removeList)
{
myDictionary.Remove(key);
}
答案 2 :(得分:2)
通常不支持迭代期间列表上的操作。预期的行为是抛出异常,但即使集合无法执行此操作,您也不能依赖于此工作。
您可以先将这些元素复制到另一个列表中,然后迭代这个要修改的新项目列表。
答案 3 :(得分:2)
没有。抛出InvalidOperationExcpetion。我同意已经枚举的项目可能是可删除的,因为有一个固定的索引。但问题如下:
SortedList的实现不够聪明,无法确定删除对枚举的进一步执行没有影响。为了保持简单和良好的表现,它不应该。
答案 4 :(得分:2)
其他人已经指出它不起作用。但是,由于集合是SortedList,因此您可以使用RemoveAt方法。
此方法具有稍好的内存配置文件,因为它不需要开销,而使用单独的列表来跟踪删除的O(n)增加。它也将具有O(n ^ 2)性能简档而不是O(n ^ 2 * log(n))。 RemoveAt方法是O(n),因为它必须执行数组复制。 Remove方法在内部调用RemoveAt之前添加O(log(n))操作以查找索引。所有这一切都可能与您无关,但如果遇到涉及大量“n”的情况,这一点很有用。
var myDictionary = new SortedList<decimal, string>();
// omitted code
int i = 0;
while (myDictionary.Count > 0 && i < myDictionary.Count)
{
if (/* predicate to use for removal */)
{
myDictionary.RemoveAt(i);
}
else
{
i++;
}
}
答案 5 :(得分:0)
另一种解决方案:
int counter= MyDictionary.Count;
if (counter == 0)
return;
for (int i = 0; i < counter;i++)
{
KeyValuePair<MyIdentifier, MyValue> key = (KeyValuePair<MyIdentifier, MyValue>)MyDictionary.ToArray()[i];
MyIdentifier identifier = null;
if (key.Key != null)
identifier = key.Key as MyIdentifier;
if (identifier != null)
if (MyCondition)
{
MyDictionary.Remove(identifier);
counter--;
}
}