Ho il classico caso di provare a rimuovere un elemento da una raccolta enumerandolo in un ciclo:
List<int> myIntCollection = new List<int>();
myIntCollection.Add(42);
myIntCollection.Add(12);
myIntCollection.Add(96);
myIntCollection.Add(25);
foreach (int i in myIntCollection)
{
if (i == 42)
myIntCollection.Remove(96); // The error is here.
if (i == 25)
myIntCollection.Remove(42); // The error is here.
}
All'inizio dell'iterazione dopo che InvalidOperationException
è stata apportata una modifica, viene generato un messaggio di errore, perché agli enumeratori non piace quando la raccolta sottostante cambia.
Devo apportare modifiche alla raccolta durante l'iterazione. Esistono molti modelli che possono essere utilizzati per evitare questo problema , ma nessuno di essi sembra avere una buona soluzione:
Non eliminare all'interno di questo ciclo, mantieni invece un "Elenco di eliminazione" separato, che elaborerai dopo il ciclo principale.
Questa è normalmente una buona soluzione, ma nel mio caso, ho bisogno che l'elemento scompaia immediatamente poiché "in attesa" fino a dopo il ciclo principale per eliminare davvero l'elemento cambia il flusso logico del mio codice.
Invece di eliminare l'elemento, è sufficiente impostare un flag sull'elemento e contrassegnarlo come inattivo. Quindi aggiungi la funzionalità del modello 1 per ripulire l'elenco.
Questo sarebbe lavoro per tutti i miei bisogni, ma significa che un sacco di codice dovrà cambiare al fine di verificare la bandiera inattiva ogni volta che un oggetto si accede. Questa è decisamente troppa amministrazione per i miei gusti.
In qualche modo incorporare le idee del modello 2 in una classe da cui deriva
List<T>
. Questo Superlist gestirà il flag inattivo, l'eliminazione di oggetti dopo il fatto e inoltre non esporrà gli elementi contrassegnati come inattivi ai consumatori dell'enumerazione. Fondamentalmente, incapsula solo tutte le idee del modello 2 (e successivamente del modello 1).Esiste una classe come questa? Qualcuno ha un codice per questo? O c'è un modo migliore?
Mi è stato detto che l'accesso
myIntCollection.ToArray()
invece dimyIntCollection
risolverà il problema e mi consentirà di eliminare all'interno del ciclo.Questo mi sembra un cattivo design pattern, o forse va bene?
Dettagli:
L'elenco conterrà molti elementi e ne rimuoverò solo alcuni.
All'interno del ciclo, farò tutti i tipi di processi, aggiungendo, rimuovendo ecc., Quindi la soluzione deve essere abbastanza generica.
L'elemento che devo eliminare potrebbe non essere l'elemento corrente nel ciclo. Ad esempio, potrei trovarmi sull'elemento 10 di un ciclo di 30 elementi e dover rimuovere l'elemento 6 o l'elemento 26. Camminare all'indietro attraverso l'array non funzionerà più a causa di ciò. ; o (