2010-06-08 17 views
8

Ho il seguente metodo, desidero rimuovere gli elementi dalla mia raccolta che corrispondono all'id del prodotto. Sembra abbastanza semplice, ma ho un'eccezione. Fondamentalmente la mia collezione sta andando fuori sincrono. Quindi qual è il modo migliore per rimuovere un oggetto da una collezione.rimozione di articoli da un elenco generico <t>

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

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

Dettagli eccezione: System.InvalidOperationException: Collection è stato modificato; operazione di enumerazione non può essere eseguita

risposta

27

La modifica di una raccolta all'interno di un loop non funziona. Per ovviare a questo, List ha alcuni metodi che consentono modifiche "batch" di una raccolta. Nel tuo caso, utilizzare:

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

grazie a conrad, stranamente non riesco a far funzionare la lamda. Non riconosce la parte "x.Product.Id". Stranamente cos il seguente funziona var query = da x in currentOrder.OrderItems dove x.Product.Id == productId select x; Il tipo di raccolta è ISet. – frosty

+0

Ok, ho risposto alla mia domanda :) Ho cambiato questa to List frosty

4

Non è possibile modificare una raccolta durante l'iterazione. Basta utilizzare un ciclo normale for anziché un ciclo foreach.

+0

:) questa era la soluzione migliore per me – EagleFox

2

Non è possibile rimuovere un elemento da una raccolta che si sta scorrendo, si potrebbe tenere traccia del orderItem, quindi rimuoverlo dopo aver terminato il ciclo

3

Con loop in questo modo non è possibile rimuovere gli elementi perché la sua in raccolta conserva la traccia degli oggetti memorizzati.

modo semplice per farlo:

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

o

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

Come vi rendete conto non è possibile rimuovere un elemento da una raccolta mentre si sta loop su di esso. Sono sicuro che qualcuno sarà in grado di fornito una soluzione più ordinato LINQ, ma il seguente dovrebbe farti andare inizialmente:

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 dato la soluzione LINQ – openshac

+0

Si noti che 'List .RemoveAll' è disponibile in .NET 2.0 e tecnicamente non è LINQ, anche se sembra simile. Questo è un vantaggio enorme rispetto a LINQ per quelle povere anime che devono mantenere la compatibilità con Windows 2000. – OregonGhost

0

"foreach" fornisce un "forward-only di sola lettura" l'iterazione di una collezione.

Come soluzione temporanea, è possibile copiare il riferimento a un'altra raccolta e quindi scorrere sulla raccolta copiata e rimuovere gli elementi da quello originale.

Problemi correlati