2010-03-30 9 views
5

Elimino el elemento de ArrayList en el bucle foreach y obtengo la siguiente excepción.Excepción durante la iteración en la colección y eliminar elementos de esa colección

Se modificó la colección; la operación de enumeración no se puede ejecutar.

¿Cómo puedo eliminar elementos en foreach,

EDIT:Puede haber un elemento para eliminar o dos o todos.

que sigue es mi código:

/* 
* 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: ¿Puede usted también consejo sobre código. ¿Es necesario que dividirlo en pequeños métodos y gestión de excepciones, etc.

excepción argumento no válido en la creación de la lista genérica ArrayList

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

{

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

Cuando utilizo el List<ArrayList> la excepción es Argumento '1': no ​​se puede convertir de 'System.Collections.ArrayList' a 'int'

attachmentsFilePath se declara como esto

ArrayList attachmentsFilePath = new ArrayList(); 

Pero cuando lo declaré como este, problema resuelto

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

Respuesta

2

puede iterar sobre una copia de la colección:

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

+1, aunque 'ArrayList' debe reemplazarse con una' Lista 'de tipo apropiado. –

+0

He creado una nueva lista (attachementsFilePath) y me da una excepción arguemnt inválida. He adjuntado iamge en el área de preguntas. – Kashif

5

No se puede eliminar un elemento de una colección al iterar sobre ella.

Puede encontrar el índice del artículo que debe eliminarse y eliminarlo una vez que haya finalizado la iteración.

int indexToRemove = 0; 

// Iteration start 

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

// End of iteration 

attachmentsFilePath.RemoveAt(indexToRemove); 

Si, sin embargo, tiene que quitar más de un elemento, iterar sobre una copia de la lista:

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

por qué no crear una lista de índices para eliminar? –

+2

Almacenar una lista de índices es arriesgado. Deberá iterar sobre la lista de índices en orden inverso o mantener un desplazamiento cada vez que elimine un elemento. –

+1

¿Es bueno crear una copia de la colección para iterar? – Kashif

0

al enumerar (o usando foreach) no se puede modificar esa colección. Si realmente desea eliminar elementos, a continuación, puede marcarlos y luego eliminarlos de la lista utilizando su método Remove

0

haga lo siguiente:

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

esta manera se crea una copia de la lista original de iterar a través

+0

He creado una nueva lista (attachementsFilePath) y me da una excepción arguemnt inválida. He adjuntado iamge en el área de preguntas. – Kashif

0

se podría bucle sobre la colección para ver qué elementos tienen que ser eliminar una nd almacenar esos índices en una colección separada. Finalmente, necesitaría recorrer los índices para eliminarlos en orden inverso y eliminarlos de la colección original.

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

Otra forma de hacerlo, empezar por el final y eliminar las que desee:

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 Iterar sobre la lista al revés en un bucle for es mi método preferido. –

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

** Descripción: ** Este ejemplo utiliza un enfoque [LINQ] (http://stackoverflow.com/tags/linq/info) para eliminar de 'list' cualquier elemento en' list' que * no * existe en ' names' ([ver demostración] (http://ideone.com/QMkkpr)). O en otras palabras, este ejemplo genera la * intersección * de 'list' y' names' (que es simplemente 'Eric'). Documentación de MSDN para [List .RemoveAll] (https://msdn.microsoft.com/en-us/library/wdka673a%28v=vs.110%29.aspx). – DavidRR

Cuestiones relacionadas