2009-07-13 7 views
8

Nella mia applicazione, _collection è una lista da cui ho bisogno di rimuovere tutti gli oggetti Utente che non corrispondono ai criteri .Qual è il modo più semplice per foreach attraverso un elenco <T> rimozione di oggetti indesiderati?

Tuttavia, il codice seguente ottiene un invalido errore operazione nella sua seconda iterazione poiché il _collection stessa è stata modificata:

foreach (User user in _collection) 
{ 
    if (!user.IsApproved()) 
    { 
     _collection.Remove(user); 
    } 
} 

ho potuto creare un'altra raccolta List e copiarli avanti e indietro, ma poi ho avere il problema dei tipi di riferimento non clonati, ecc.

C'è un modo per fare quanto sopra più elegantemente della copia di _collection su un'altra variabile di lista?

risposta

54
_collection.RemoveAll(user => !user.IsApproved()); 

Se sei ancora sul 2.0:

_collection.RemoveAll(delegate(User u) { return !u.IsApproved(); }); 

A proposito, se non si vuole toccare la lista originale, è possibile ottenere un altro elenco delle approvato utenti con:

_collection.FindAll(user => user.IsApproved()); 
+0

o '_collection.FindAll (user => user.IsApproved());' per eliminare negazioni. –

+0

_collection.FindAll restituirà ** un'altra ** raccolta. È molto diverso dal cambiare la collezione iniziale (potrebbero esserci casi in cui alcuni altri oggetti contengono riferimenti alla stessa lista e ne hai bisogno cambiando, invece di crearne un'altra). –

4

È sempre possibile iniziare dall'indice superiore e scorrere verso il basso verso 0:

for (int i = _collection.Count - 1; i >= 0; i--) 
{ 
    User user = _collection[i]; 
    if (!user.IsApproved()) 
    { 
     _collection.RemoveAt(i); 
    } 
} 

risposta di Mehrdad sembra maledettamente elegante, però.

+0

Questo sembra contenere un bug. Considera il caso di una raccolta con due elementi, il primo dei quali non è approvato. Il primo viene rimosso, quindi la raccolta [1] diventa outs of bounds. –

+0

Steven: Nel caso in cui descrivi il codice precedente avresti già controllato la raccolta [1] (che dopo aver rimosso la raccolta [0] diventa raccolta [0]) poiché sta iterando dall'alto verso il basso. Quindi non ci dovrebbero essere errori fuori dai limiti. –

+0

Va bene. Passeggia di nuovo e vedrai che va bene. –

0

Ogni volta che c'è una possibilità che una collezione sarà modificato in un ciclo, optare per un ciclo for invece. La soluzione offerta da Mehrdad è adorabile e sicuramente vale la pena provare!

Ecco il codice che trovo utile quando si tratta di collezioni modificabili:

for(int index=0;index < _collection.Count; index++) 
{ 
    if (!_collection[index].IsApproved) 
    { 
     _collection.RemoveAt(index); 
     index--; 
    } 
} 
Problemi correlati