E 'sicuro di cancellare dal SortedList durante l'iterazione
-
01-10-2019 - |
Domanda
La mia domanda è è sicuro per enumeratore per rimuovere elemento dalla 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);
}
Soluzione
In questo modo un'eccezione -. Non è possibile modificare una raccolta, mentre l'iterazione su di esso
Se ci pensate un po ', si capirà il perché. Se aggiunta o la rimozione della collezione è stato permesso, si sarebbe non essere più l'iterazione sulla stessa collezione -. Si hanno o troppi (aggiunta) o non abbastanza articoli (rimozione)
Altri suggerimenti
Come già detto quello che stai cercando di fare non è possibile. Tuttavia, una soluzione alternativa sarebbe quella di mantenere semplicemente un elenco di articoli contrassegnati per l'eliminazione e quindi rimuovere questi afterwords. Vorrei anche optare per un foreach
piuttosto che un ciclo while
, meno codice per es.
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);
}
}
Oppure, se si sta semplicemente cercando di recuperare gli elementi per la cancellazione, l'uso LINQ
var removeList = myDictionary.Where(pair => pair.Key > 1).Select(k => k.Key).ToList();
Poi basta rimuoverli dalla lista.
// remove from the main collection
foreach (var key in removeList)
{
myDictionary.Remove(key);
}
Operazioni in lista durante le iterazioni non sono supportati in generale. Il comportamento previsto è un'eccezione, ma anche se una collezione non riesce a fare questo non è necessario fare affidamento su questo funziona correttamente.
È possibile prima copiare gli elementi in un'altra lista e poi iterare su questo nuovo elenco di elementi da modificare.
No. Un InvalidOperationExcpetion è gettato. Sono d'accordo che gli elementi già elencati potrebbero essere eliminabile in quanto non v'è un indice fisso. Tuttavia, il problema è il seguente:
L'attuazione di SortedList non è abbastanza intelligente per capire che ciò non ha alcun effetto sul l'ulteriore esecuzione del enumerabile. E per mantenere le cose semplici e che funziona bene, non dovrebbe.
Come altri hanno già fatto notare che non funzionerà. Tuttavia, dato che la collezione è un SortedList è possibile utilizzare il metodo RemoveAt.
Questo metodo ha un profilo leggermente migliore memoria poiché richiede alcun overhead in contrapposizione ad un incremento O (n) utilizzando un elenco separato per tenere traccia delle rimozioni. Sarebbe anche un O (n ^ 2) il profilo delle prestazioni rispetto a O (n ^ 2 * log (n)). Il metodo RemoveAt è O (n) in quanto deve eseguire una copia matrice. Il metodo Remove aggiunge un'operazione O (log (n)) per trovare l'indice prima di chiamare internamente RemoveAt. Tutto questo è probabilmente di nessun interesse per voi, ma è conoscenza utile nel caso in cui si esegue in circostanze che comportino un sacco di '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++;
}
}
Un altra soluzione:
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--;
}
}