3

私の質問は、列挙子が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);
}
4

6 に答える 6

8

これにより例外がスローされます。コレクションを反復処理している間はコレクションを変更できません。

少し考えてみると、その理由がわかります。コレクションへの追加またはコレクションからの削除が許可されている場合、同じコレクションを反復処理する必要はありません。アイテムが多すぎる(追加)か、アイテムが不足している(削除)かのどちらかです。

于 2010-04-23T12:38:04.893 に答える
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);
}
于 2010-04-23T12:54:10.447 に答える
2

他の人がすでに指摘しているように、それは機能しません。ただし、コレクションはSortedListであるため、RemoveAtメソッドを使用できます。

この方法は、削除を追跡するために別のリストを使用してO(n)を増やすのとは対照的に、オーバーヘッドを必要としないため、わずかに優れたメモリプロファイルを備えています。また、O(n ^ 2 * log(n))とは対照的に、O(n ^ 2)のパフォーマンスプロファイルがあります。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++;
  }
}
于 2010-04-23T14:23:27.843 に答える
2

反復中のリストの操作は、一般的にサポートされていません。予想される動作は例外をスローすることですが、コレクションがこれを実行できない場合でも、これが正しく機能することに依存してはなりません。

最初に要素を別のリストにコピーしてから、変更するアイテムのこの新しいリストを反復処理できます。

于 2010-04-23T12:38:28.677 に答える
2

いいえ。InvalidOperationExcpetionがスローされます。インデックスが固定されているため、すでに列挙されているアイテムが削除可能になる可能性があることに同意します。ただし、問題は次のとおりです。

SortedListの実装は、削除が列挙可能なもののその後の実行に影響を与えないことを理解するのに十分賢いものではありません。そして、それをシンプルでうまく機能させるために、そうすべきではありません。

于 2010-04-23T12:45:01.513 に答える
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--;
                    }
            }
于 2013-04-17T04:39:50.500 に答える