我的问题是,枚举者可以从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);
}
有帮助吗?

解决方案

这将引发异常 - 您无法在迭代时修改集合。

如果您考虑一点,您将理解原因。如果允许从集合中添加或删除,您将不再在同一集合上迭代 - 您要么有太多(添加)或不足的项目(删除)。

其他提示

正如已经说明您要做的事情是不可能的。但是,另一种解决方案是简单地维护标记为删除的项目列表,然后删除这些后词。我也会选择一个 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);
}

一般而言,在迭代期间列表上的操作不支持。预期的行为是抛出例外,但是即使收藏不这样做,您也不能正确依靠此工作。

您可以首先将元素复制到另一个列表中,然后在要修改的项目列表中迭代。

否。我同意,由于有固定的索引,因此已经枚举的项目可能是可删除的。但是,问题是以下内容:

SortedList的实施不够聪明,无法确定删除不会影响枚举的进一步执行。为了保持简单和表现良好,不应该。

正如其他人已经指出的那样,它将行不通。但是,由于该集合是一个排序列表,因此您可以使用removeat方法。

此方法具有更好的内存配置文件,因为它不需要开销,而不是使用单独列表的O(n)增加来跟踪删除。与O(n^2 * log(n))相反,它也具有O(n^2)性能配置文件。 REMOVEAT方法为O(n),因为它必须执行数组副本。删除方法添加了O(log(n))操作以在内部调用removeat之前查找索引。所有这些可能都不关心您,但是如果您遇到涉及很多“ 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++;
  }
}

另一个解决方案:

            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--;
                    }
            }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top