2010-06-08 39 views
8

Tengo el siguiente método, deseo eliminar elementos de mi colección que coincidan con el Id del producto. Parece bastante sencillo, pero recibo una excepción. Básicamente mi colección se está desincronizando. Entonces, ¿cuál es la mejor manera de eliminar un elemento de una colección?eliminar elementos de una lista genérica <t>

public void RemoveOrderItem(Model.Order currentOrder, int productId) 
{ 

    foreach (var orderItem in currentOrder.OrderItems) 
    { 
     if (orderItem.Product.Id == productId) 
     { 
      currentOrder.OrderItems.Remove(orderItem); 
     } 
    } 
} 

Excepción: System.InvalidOperationException: La colección se modificó; la operación de enumeración no se puede ejecutar

Respuesta

27

La modificación de una colección dentro de un bucle no funciona. Para solucionar esto, List tiene algunos métodos que permiten modificaciones "por lotes" de una colección. En su caso, use:

currentOrder.OrderItems.RemoveAll(x => x.Product.Id == productId) 
+0

gracias conrad, raro, no puedo hacer que la lamda funcione. No reconoce la parte "x.Product.Id". Extraño porque los siguientes trabajos var query = from x en currentOrder.OrderItems donde x.Product.Id == productId select x; El tipo de colección es ISet. – frosty

+0

ok, respondí mi propia pregunta :) He cambiado esto a List frosty

4

No puede modificar una colección mientras la itera. Solo use un bucle normal for en lugar de un bucle foreach.

+0

:) esta fue la mejor solución para mí – EagleFox

2

No se puede eliminar un elemento de una colección que se está iterando a través, usted podría hacer un seguimiento del artículo de pedido, y luego retirarlo después de terminar un bucle

3

Por bucle de esta manera no se puede quitar porque está en artículos colección mantiene la pista de los artículos almacenados.

Una forma sencilla de hacer esto:

authorsList.RemoveAll(x => x.ProductId == productId); 

o

authorsList = authorsList.Where(x => x.ProductId!= productId).ToList(); 
1

Como se da cuenta de que no se puede eliminar un elemento de una colección mientras se recorre sobre ella. Estoy seguro de que alguien será capaz proporcionado una solución LINQ más ordenado, pero lo que sigue debe conseguir que ir inicialmente:

public void RemoveOrderItem(Model.Order currentOrder, int productId) 
{ 
    var selectedOrderItem = null; 
    foreach (var orderItem in currentOrder.OrderItems) 
    { 
     if (orderItem.Product.Id == productId) 
     { 
      selectedOrderItem = orderItem; 
      break; 
     } 
    } 

    if(selectedOrderItem != null) 
     currentOrder.OrderItems.Remove(selectedOrderItem); 
} 
+0

Konrad Rudolph ha dado la solución LINQ – openshac

+0

Tenga en cuenta que 'List .RemoveAll' está disponible en .NET 2.0 y técnicamente no es LINQ, aunque parece similar. Esa es una gran ventaja sobre LINQ para esas pobres almas que tienen que mantener la compatibilidad con Windows 2000. – OregonGhost

0

"foreach" proporciona una "sólo avance de sólo lectura" iteración de una colección.

Como solución alternativa, puede copiar la referencia a otra colección y luego iterar en la colección copiada y eliminar los elementos de la colección original.

Cuestiones relacionadas