2012-04-16 23 views
12

puedo ver por qué esto no está permitido:Eliminar foreach interior con LINQ donde

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

pero ¿qué tal esto?

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

No entiendo por qué esto falla. El método "Where()" obviamente no devuelve la colección original, por lo que no estoy enumerando alrededor de la colección original cuando intento eliminar algo de ella.

+0

Hay algo que no entiendo sobre esta cosa "Cosa". Ciertamente no es una cosa tipo de construcción ¿verdad? Alguien me ilumina ... – Deb

+0

Lo siento si la pregunta era confusa. La cosa podría ser cualquier clase y myCollecion es cualquier ICollection . FWIW Eric ha entendido y respondido completamente a mi pregunta original, por lo que está cerrada por lo que a mí respecta. – Andy

Respuesta

26

No entiendo por qué esto falla.

Supongo que su pregunta es "¿por qué esto no funciona?" (Se le olvidó preguntar en realidad una pregunta en su pregunta.)

El método "Donde()", obviamente, no va a regresar la colección original

correcta. "Where" devuelve un IEnumerable<T> que representa la colección con un filtro puesto encima.

así que no estoy enumerando alrededor de la colección original cuando intento eliminar algo de ella.

Incorrecto. Usted es enumerando la colección original. Está enumerando la colección original con un filtro sobre ella.

Cuando llama a "Dónde" no evalúa con entusiasmo el filtro y produce una nueva copia de la colección original con el filtro aplicado. Por el contrario, le da un objeto que enumera la colección original, pero omite los elementos que no coinciden con el filtro.

Cuando estás en una tienda y dices "muéstrame todo", el chico que te muestra todo te muestra todo. Cuando dices "ahora solo muéstrame las manzanas que están entre $ 1 y $ 5 por kilogramo", no estás construyendo una tienda completamente nueva que solo tenga manzanas en ella.Estás viendo exactamente la misma colección de cosas que antes, solo con un filtro.

2

Es porque la colección no se debe modificar con el ciclo foreach. Intenta eliminarlo antes de que se ejecute todo el ciclo foreach. Por lo tanto, fracasará.

+1

Creo que estás cerca con la segunda parte de tu respuesta ... ¿estás buscando una evaluación perezosa? –

6

La segunda declaración devuelve un IEnumerable<> que funciona en su lista. Éste debe estar bien:

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

+1 por mencionar el IEnumerable –

+0

gracias, esta es la solución que he implementado, pero marqué a Eric como la respuesta porque lo que realmente quería era saber lo que estaba sucediendo debajo de – Andy

12

probar este código

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

Usted puede hacer:

myCollection.RemoveAll(shouldDelete); 
+0

Gracias, en realidad quería hacer algo más dentro del ciclo así que la sugerencia de Likurg fue mejor para mí, pero te he hecho +1 :-) – Andy

+2

... ¡si el tipo de 'myCollection' tiene un método RemoveAll! 'List ' hace, pero muchos tipos de colección no lo hacen. – phoog

1

Dónde método de extensión filtrar los valores de la colección basado en el predicado pasado y devuelve IEnumerable . Por lo tanto, no puede modificar la colección durante la iteración.

Puede usar RemoveAll() para su propósito.