¿Es seguro eliminar de SortedList durante la iteración
-
01-10-2019 - |
Pregunta
Mi pregunta es ¿es seguro para el empadronador a Quitar elemento de 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);
}
Solución
Esto producirá una excepción -. No puede modificar una colección al iterar sobre ella
Si se piensa en ello un poco, se entiende por qué. Si la adición o eliminación de la colección estaba permitido, ya no debería estar interactuando sobre la misma colección -. Usted o tiene demasiados (adición) o no suficientes elementos (eliminación)
Otros consejos
Como ya se ha dicho lo que está buscando hacer no es posible. Sin embargo, una solución alternativa sería mantener simplemente una lista de elementos marcados para su eliminación y luego eliminar estos epílogos. Lo haría también optan por un foreach
en lugar de un bucle while
, por ejemplo menos código.
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);
}
}
O si simplemente está tratando de recuperar los elementos para su eliminación, el uso de LINQ
var removeList = myDictionary.Where(pair => pair.Key > 1).Select(k => k.Key).ToList();
A continuación, sólo eliminarlos de la lista.
// remove from the main collection
foreach (var key in removeList)
{
myDictionary.Remove(key);
}
Operaciones en la lista durante iteraciones no se admiten en general. El comportamiento esperado es lanzar una excepción, pero incluso si falla una colección de hacer esto que no debe confiar en esta trabajando correctamente.
En primer lugar, puede copiar los elementos en otra lista y luego iterar sobre esta nueva lista de elementos que desea modificar.
No. Un InvalidOperationExcpetion es lanzada. Estoy de acuerdo en que los elementos ya enumerados podrían ser suprimible ya que hay un índice fijo. Sin embargo, la cuestión es la siguiente:
La implementación de SortedList no es lo suficientemente inteligente como para darse cuenta de que la eliminación se no tienen ningún efecto sobre la ulterior ejecución del enumerable. Y que sea sencillo y un buen rendimiento, no debería.
Como otros ya han señalado que no va a funcionar. Sin embargo, puesto que la colección es un SortedList puede utilizar el método RemoveAt.
Este método tiene un poco mejor perfil de memoria ya que requiere ninguna sobrecarga en contraposición a un aumento O (n) utilizando una lista separada para realizar un seguimiento de las extracciones. También tendría un O (n ^ 2) perfil de rendimiento en lugar de O (n ^ 2 * log (n)). El método RemoveAt es O (n), ya que debe realizar una copia de matriz. El método Remove añade una operación O (log (n)) para encontrar el índice antes de llamar internamente RemoveAt. Todo esto es, probablemente, de ninguna preocupación para usted, pero es conocimiento útil en caso de que tenga las situaciones que implican una gran cantidad de '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++;
}
}
Una otra solución:
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--;
}
}