2010-02-27 19 views
12

Estoy usando un diccionario y quiero cambiarlo mientras lo enumero, pero parece que no está permitido. ¿Cómo puedo hacer esto?Modificar .NET Dictionary mientras se lo enumera

Gracias

+0

¿Quieres cambiar la clave o el valor? –

+1

No querrás reconstruir un puente mientras estás en él, ¿sí? Es posible que desee implementar de una manera diferente. –

+5

@ [o.k.w] Créalo o no, pero así es como se construyen y modifican/reparan enormes puentes. Y si tengo un gran diccionario y debo modificar cada valor, prefiero no clonar primero las claves. –

Respuesta

5

Debe almacenar la clave u objeto que desea eliminar y romper el ciclo, y luego usar el método de eliminar para eliminar el objeto del diccionario.

Espero que esto ayude

1

me contestaron que here con respecto a la cola de pero la respuesta es la misma. No puede enumerar con foreach y modificar la colección al mismo tiempo.

10

No, básicamente. Explícitamente no es compatible. A partir de los documentos de Dictionary<,>.GetEnumerator():

Un enumerador sigue siendo válida mientras la colección se mantiene sin cambios. Si se realizan cambios en en la colección, , como agregar, modificar o eliminar elementos , el enumerador es irrevocablemente invalidado y su comportamiento no está definido.

Normalmente, la mejor manera es recordar las modificaciones que desea realizar y luego realizarlas. O puede tomar una copia del diccionario para comenzar y luego repetir a través del ese mientras modifica el original. Si pudieras darnos más información sobre lo que estás tratando de hacer, eso ayudaría.

Una vez dicho esto, la nueva clase ConcurrentDictionary en .NET 4.0 hace permiso de esto - pero los resultados de la iteración no están garantizados - usted puede ver los cambios mientras se está iterando, o puede que no.

+1

Quizás lo más exacto es que no pudieron encontrar una buena forma de lanzar IllegalOperationException para ConcurrentDictionary. Va a causar un * montón * de problemas. Ciertamente no lo recomendaría. –

+1

@nobugz: dudo mucho que sea porque * no * arrojaron IllegalOperationException. El objetivo de las colecciones simultáneas es que puede hacer cosas * concurrentemente * con ellas, lo que incluye iterar.Ahora, por lo general, desea modificar la colección en el mismo hilo iterativo (como es fácil de evitar) pero en el caso general es mucho más difícil. –

+0

el por qué no es realmente relevante, el hecho de que no arroje la excepción es. Hay muchos programadores aquí que toman tus publicaciones como evangelio, tengo que instarte a que consideres las ramificaciones de tu consejo. Al mutar el diccionario mientras se lo itera, ya sea por el mismo hilo o por otro, he Heisenbug escrito sobre él. Al mirar el código fuente reflejado, ConcurrentDirectionary no hace nada para evitar contratiempos. Y los documentos de MSDN guardan silencio al respecto. –

1

Me encontré con una situación similar en el trabajo. Necesitaba modificar un diccionario mientras lo hacía de forma iterativa haciéndolo más pequeño hasta que no me quedaban las llaves/valores.

Empecé por crear una lista de claves "para eliminar", pero fue muy lento con toda la otra lógica que tuve que implementar. Alternativamente, terminé iterando a través del diccionario hacia atrás. Como está atravesando el diccionario de atrás hacia adelante, la iteración no arrojará un error.

Después de Saco mi lógica relacionada con el trabajo, parece tonto, pero te prometo que funciona y se ve algo como:

Dictionary<int, List<int>> dict = new Dictionary<int, List<int>>(); 
    while(dict.Any()) 
    { 
     foreach(var key in dict.Keys.Reverse()) 
     { 
      if(//conditional) 
      { 
       dict.Remove(key); 
      } 
      else 
      { 
       //do something with dict[key] 
      } 
     } 
    } 
Cuestiones relacionadas