2010-03-30 10 views
5

Rimuovi elemento da ArrayList nel ciclo foreach e ottieni l'eccezione follwing.Eccezione durante l'iterazione alla raccolta e rimozione di elementi da quella raccolta

Raccolta modificata; l'operazione di enumerazione potrebbe non essere eseguita.

Come posso rimuovere elementi in foreach,

EDIT:Ci potrebbe essere un elemento da rimuovere o due o tutti.

seguito è il mio codice:

/* 
* Need to remove all items from 'attachementsFielPath' which does not exist in names array. 
*/ 

try 
{ 
    string attachmentFileNames = txtAttachment.Text.Trim(); // Textbox having file names. 
    string[] names = attachmentFileNames.Split(new char[] { ';' }); 

    int index = 0; 

    // attachmentsFilePath is ArrayList holding full path of fiels user selected at any time. 
    foreach (var fullFilePath in attachmentsFilePath) 
    { 
     bool isNeedToRemove = true; 

     // Extract filename from full path. 
     string fileName = fullFilePath.ToString().Substring(fullFilePath.ToString().LastIndexOf('\\') + 1); 

     for (int i = 0; i < names.Length; i++) 
     { 
     // If filename found in array then no need to check remaining items. 
     if (fileName.Equals(names[i].Trim())) 
     { 
      isNeedToRemove = false; 
      break; 
     } 
     } 

     // If file not found in names array, remove it. 
     if (isNeedToRemove) 
     { 
     attachmentsFilePath.RemoveAt(index); 
     isNeedToRemove = true; 
     } 

     index++; 
    } 
} 
catch (Exception ex) 
{ 
    throw ex; 
} 

EDIT: si può anche consigli sul codice. Ho bisogno di rompere in piccoli metodi e gestione delle eccezioni, ecc

eccezione Invalid argument Sulla creazione elenco generico da ArrayList

foreach (var fullFilePath in new List<string>(attachmentsFilePath)) 

{

alt text http://img641.imageshack.us/img641/1628/invalidargument1.png

Quando uso il List<ArrayList> l'eccezione è Argomento '1': impossibile convertire da 'System.Collections.ArrayList' a 'int'

attachmentsFilePath è dichiarato come questo

ArrayList attachmentsFilePath = new ArrayList(); 

Ma quando ho dichiarato in questo modo, problema risolto

List<ArrayList> attachmentsFilePath = new List<ArrayList>(); 

risposta

2

È possibile iterare su una copia della collezione:

foreach(var fullFilePath in new ArrayList(attachmentsFilePath)) 
{ 
    // do stuff 
} 
+1

+1, anche se 'ArrayList' dovrebbe essere sostituito con un' Elenco 'digitato correttamente. –

+0

Ho creato una nuova lista (attachementsFilePath) e mi dà un'eccezione arguemnt non valida. Ho allegato iamge nell'area delle domande. – Kashif

5

Non è possibile rimuovere un elemento da una raccolta, mentre l'iterazione su di esso.

È possibile trovare l'indice dell'articolo che deve essere rimosso e rimuoverlo una volta completata l'iterazione.

int indexToRemove = 0; 

// Iteration start 

if (fileName.Equals(names[i].Trim())) 
{ 
    indexToRemove = i; 
    break; 
} 

// End of iteration 

attachmentsFilePath.RemoveAt(indexToRemove); 

Se, tuttavia, è necessario rimuovere più di un oggetto, iterare su una copia della lista:

foreach(string fullFilePath in new List<string>(attachmentsFilePath)) 
{ 
    // check and remove from _original_ list 
} 
+2

Perché non creare un elenco di indici da rimuovere? –

+2

La memorizzazione di un elenco di indici è rischiosa. Dovrai eseguire iterazioni sull'elenco degli indici al contrario o mantenere un offset ogni volta che rimuovi un elemento. –

+1

La creazione di una copia della raccolta per iterare è un buon approccio? – Kashif

0

durante l'enumerazione (o utilizzando foreach) non è possibile modificare tale raccolta. Se davvero si vuole rimuovere gli elementi, allora si può segnare e poi rimuoverli dalla lista utilizzando il metodo Remove

0

effettuare le seguenti operazioni:

foreach (var fullFilePath in new List(attachmentsFilePath)) 
{ 

in questo modo si crea una copia della lista originale per iterare attraverso

+0

Ho creato una nuova lista (attachementsFilePath) e mi dà un'eccezione arguemnt non valida. Ho allegato iamge nell'area delle domande. – Kashif

0

Si potrebbe loop all'interno di una collezione per vedere quali articoli devono essere eliminare un nd memorizza quegli indici in una raccolta separata. Infine, è necessario eseguire il ciclo degli indici da eliminare in ordine inverso e rimuoverli dalla raccolta originale.

list<int> itemsToDelete 

for(int i = 0; i < items.Count; i++) 
{ 
    if(shouldBeDeleted(items[i])) 
    { 
     itemsToDelete.Add(i); 
    } 
} 

foreach(int index in itemsToDelete.Reverse()) 
{ 
    items.RemoveAt(i); 
} 
6

Un altro modo di farlo, cominciare dalla fine e cancellare quelli che si desidera:

List<int> numbers = new int[] { 1, 2, 3, 4, 5, 6 }.ToList(); 
for (int i = numbers.Count - 1; i >= 0; i--) 
{ 
    numbers.RemoveAt(i); 
} 
+1

+1 L'iterazione sulla lista all'indietro in un ciclo for è il mio metodo preferito. –

2
List<string> names = new List<string>() { "Jon", "Eric", "Me", "AnotherOne" }; 
    List<string> list = new List<string>() { "Person1", "Paerson2","Eric"}; 

    list.RemoveAll(x => !names.Any(y => y == x)); 
    list.ForEach(Console.WriteLine); 
+0

** Descrizione: ** Questo esempio utilizza un approccio [LINQ] (http://stackoverflow.com/tags/linq/info) per rimuovere da 'list' qualsiasi elemento in' list' che * non * esiste in ' names' ([vedi demo] (http://ideone.com/QMkkpr)). O in altre parole, questo esempio restituisce * l'intersezione * di 'list' e' names' (che è semplicemente 'Eric'). Documentazione MSDN per [List . Rememont All] (https://msdn.microsoft.com/en-us/library/wdka673a%28v=vs.110%29.aspx). – DavidRR

Problemi correlati