2012-04-16 14 views
12

Posso capire perché questo non è consentito:Eliminare foreach all'interno con LINQ in cui

foreach (Thing t in myCollection) { 
    if (shouldDelete(t) { 
     myCollection.Delete(t); 
    } 
} 

ma come su questo?

foreach (Thing t in myCollection.Where(o=>shouldDelete(o)) { 
    myCollection.Delete(t); 
} 

Non capisco perché questo non funziona. Il metodo "Dove()" ovviamente non restituisce la raccolta originale, quindi non sto elencando intorno alla collezione originale quando provo a rimuovere qualcosa da essa.

+0

C'è qualcosa che non capisco di questa cosa "Cosa". Non è certamente una cosa tipo costruita? qualcuno mi illumina .... – Deb

+0

Scusa se la domanda è stata confusa. La cosa potrebbe essere qualsiasi classe e myCollecion è qualsiasi ICollection . FWIW Eric ha completamente capito e risposto alla mia domanda originale, quindi è chiuso per quanto mi riguarda. – Andy

risposta

26

Non capisco perché questo non funziona.

Suppongo che la tua domanda sia "perché questo non funziona?" (Hai dimenticato di chiedere in realtà una domanda nella sua interrogazione.)

Il metodo "Dove()" ovviamente non restituisce la collezione originale

corretta. "Dove" restituisce un IEnumerable<T> che rappresenta la raccolta con un filtro posto sopra.

quindi non sto elencando intorno alla raccolta originale quando provo a rimuovere qualcosa da esso.

errato. È che elenca la raccolta originale. Stai elencando la raccolta originale con un filtro sopra di essa.

Quando si chiama "Dove" non valuta il filtro in modo impaziente e produce una nuova copia della serie originale con il filtro applicato. Piuttosto, ti dà un oggetto che enumera la collezione originale, ma salta gli oggetti che non corrispondono al filtro.

Quando sei in un negozio e dici "mostrami tutto", il ragazzo che ti mostra tutto ti mostra tutto. Quando dici "ora mostrami solo le mele che sono tra $ 1 e $ 5 al chilogrammo", non stai costruendo un negozio completamente nuovo che contiene solo mele.Stai guardando esattamente la stessa collezione di cose come prima, solo con un filtro su di esso.

2

È perché la raccolta non deve essere modificata con il ciclo foreach. Tenta di cancellarlo prima che venga eseguito l'intero ciclo foreach. Quindi fallirà.

+1

Penso che tu sia vicino alla seconda parte della tua risposta ... stai cercando una valutazione pigra? –

6

La seconda dichiarazione restituisce un IEnumerable<> operativo nell'elenco. Questo dovrebbe essere a posto:

uso
foreach (Thing t in myCollection.Where(o=>shouldDelete(o).ToList()) { 
    myCollection.Delete(t); 
} 
+0

+1 per aver menzionato l'IEnumerable –

+0

grazie, questa è la soluzione che ho implementato, ma ho segnato Eric come risposta perché quello che volevo veramente era sapere cosa stava succedendo sotto – Andy

12

provare questo codice

myCollection.RemoveAll(x => x.shouldDelete(x)); 
9

Si può fare:

myCollection.RemoveAll(shouldDelete); 
+0

Grazie, in realtà volevo fare qualcos'altro all'interno del loop quindi il suggerimento di Likurg è stato migliore per me, ma ho fatto +1 tu :-) – Andy

+2

... se il tipo di 'myCollection' ha un metodo RemoveAll! 'Lista , ma molti tipi di raccolta no. – phoog

1

Dove metodo di estensione filtrare i valori di raccolta in base predicato passato e restituisce IEnumerable . Quindi non è possibile modificare la raccolta durante l'iterazione.

È possibile utilizzare RemoveAll() per il proprio scopo.

Problemi correlati