2010-02-27 15 views
12

Sto usando un dizionario e voglio cambiarlo mentre lo enumero attraverso di esso, ma sembra che questo non sia permesso. Come posso fare questo?Modifica del dizionario di .NET durante l'enumerazione attraverso di esso

Grazie

+0

Vuoi cambiare la chiave o il valore? –

+1

Non vorrai ricostruire un ponte mentre ci sei, vero? Potresti voler implementare in un modo diverso. –

+5

@ [o.k.w] Ci crediate o no, ma è così che vengono costruiti, modificati e riparati enormi ponti. E se ho un dizionario enorme e devo modificare ogni valore, preferirei non clonare prima i tasti. –

risposta

5

È necessario memorizzare la chiave o l'oggetto che si desidera eliminare e interrompere il ciclo, quindi utilizzare il metodo remove per eliminare l'oggetto dal dizionario.

Spero che questo aiuti

1

ho risposto che here rispetto alla coda di ma la risposta è la stessa. Non è possibile enumerare con foreach e modificare la raccolta contemporaneamente.

10

No, in pratica. È esplicitamente non supportato. Dalla documentazione per Dictionary<,>.GetEnumerator():

Un enumeratore rimane valido finché la collezione rimane invariato. Se le modifiche vengono apportate alla raccolta, come aggiungere, modificare o eliminare elementi , l'enumeratore è irrecuperabilmente invalidato e il suo comportamento non è definito.

In genere, il modo migliore è ricordare le modifiche che si desidera apportare e quindi eseguirle in un secondo momento. Oppure puoi prendere una copia del dizionario per iniziare e quindi scorrere lo del mentre modifichi l'originale. Se potessi darci più informazioni su ciò che stai cercando di fare, sarebbe di grande aiuto.

Detto questo, la nuova classe ConcurrentDictionary in .NET 4.0 fa permesso questo - ma i risultati dell'iterazione non sono garantiti - si possono vedere i cambiamenti, mentre si sta iterazione, o non può.

+1

Forse più precisamente è che non sono riusciti a trovare un buon modo per lanciare IllegalOperationException per ConcurrentDictionary. Sta per causare un sacco di guai. Io di certo non lo consiglierei. –

+1

@nobugz: dubito fortemente che sia perché * non possono * lanciare IllegalOperationException. Il punto delle raccolte simultanee è che puoi fare cose * contemporaneamente * con loro - che include l'iterazione.Ora di solito vuoi modificare la raccolta nello stesso thread che sta iterando (è abbastanza facile da evitare), ma nel caso generale è molto più difficile. –

+0

il perché non è veramente rilevante, il fatto che non faccia eccezione è. Ci sono molti programmatori qui che prendono i tuoi post come vangelo, devo esortarti a considerare le ramificazioni dei tuoi consigli. Mutando il dizionario mentre lo itera, sia con lo stesso thread sia con un altro, Heisenbug ha scritto tutto su di esso. Dall'osservazione del codice sorgente riflesso, ConcurrentDirectionary non fa nulla per evitare contrattempi. E i documenti MSDN ne sono completamente silenziosi. –

1

Mi sono imbattuto in una situazione simile al lavoro. Avevo bisogno di modificare un dizionario mentre lo rendevo più piccolo fino a quando non avevo lasciato le chiavi/i valori.

Ho iniziato creando un elenco di chiavi "da rimuovere", ma era dolorosamente lento con tutte le altre logiche che dovevo implementare. In alternativa, ho finito per scorrere il dizionario all'indietro. Dal momento che stai attraversando il dizionario da dietro in avanti, l'iterazione non genera un errore.

Dopo tiro fuori la mia logica lavoro correlato, sembra stupido, ma vi prometto che funziona e sembra qualcosa di simile:

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] 
      } 
     } 
    } 
Problemi correlati