2013-07-02 17 views
5

Sto scrivendo un download manager multi-threaded in cui scaricare informazioni è gestito da una classe che ho scritto (chiamato DownloadOperation). I download sono contenuti in un elenco (chiamato download). Devo rimuovere gli oggetti dall'elenco quando una funzione nella classe (queryCompletata) restituisce true, ma ha scoperto che gli elementi non possono essere rimossi dagli elenchi dall'interno di un ciclo foreach. Qual è il modo migliore per avere lo stesso effetto. Sono relativamente nuovo a C# quindi perdoni la mia stupidità.Rimozione di elementi da un elenco quando una condizione è soddisfatta

private void removeInactiveDownloads() 
    { 
     foreach (DownloadOperation dl in download) 
     { 
      if (dl.queryComplete() == true) 
      { 
       // if download is no longer in progress it is removed from the list. 
       download.Remove(dl); 
      } 
     } 
    } 

Modifica - Corretto un errore nel codice di esempio.

risposta

3

Iterate all'indietro in un ciclo For invece di un ciclo foreach

for(int i = download.Count; i >= 0; i--) 
{ 
    if (download[i].queryComplete()) 
    { 
     // if download is no longer in progress it is removed from the list. 
     download.RemoveAt(i); 
    } 
} 
+0

Grazie mille! Sembra funzionare perfettamente. – user2544563

+0

Prego :) (anche se la query LINQ di Patashu è molto più concisa) – keyboardP

+1

+1 La chiave è che non si sta utilizzando un oggetto 'IEnumerator'. –

11

List<T> ha un metodo

public int RemoveAll(
    Predicate<T> match 
) 

che rimuove tutti gli elementi che corrispondono a un predicato: http://msdn.microsoft.com/en-us/library/wdka673a.aspx

Perciò io propongo qualcosa Mi piace:

download.RemoveAll(x => x.queryComplete()); 

(si noti che == true non è necessaria in quanto .queryComplete() restituisce già vero o falso!)

1

risposta di Patashu è la soluzione migliore in generale, ma in base al codice di esempio vorrei suggerire di prendere un altro approccio del tutto.

Sei polling la lista scaricare periodicamente per trovare quelli completati? L'abbonamento all'evento sarebbe probabilmente una soluzione migliore. Dal momento che sei nuovo a C#, nel caso in cui tu non sappia la lingua ha il supporto integrato per questo modello: Events

Un download può generare un evento Completed quando viene completato, il quale è sottoscritto dal codice che gestisce la lista, qualcosa come:

private void AddDownload(DownloadOperation dl) { 
    download.Add(dl); 
    dl.Completed += (s, e) => download.Remove(dl); 
} 
Problemi correlati