2010-08-08 6 views
5

¿Puedo agregar nodos de forma segura al contenedor LinkedList dentro de la instrucción foreach? ¿Hay alguna diferencia si uso while loop? ¿O nunca está permitido y puede causar algunos problemas?Agregar nodos a LinkedList <T> en foreach

foreach(var node in myList) 
{ 
    if(condition) 
     myList.AddLast(new MyNode()); 
} 

Será siempre trabajo ?

Respuesta

6

No puede modificar una colección mientras la enumera.

Desde el docs for LinkedList<T>.GetEnumerator:

Un enumerador sigue siendo válida mientras la colección se mantiene sin cambios. Si se realizan cambios en en la colección, , como agregar, modificar o eliminar elementos , el enumerador es irrevocablemente invalidado y su comportamiento no está definido.

En la práctica, creo que siempre lanzará un InvalidOperationException, a pesar del comportamiento oficialmente indefinido.

EDIT: Se le preguntó en un comentario si un bucle while ayudaría ... usando un bucle while GetEnumerator/MoveNext/Current no lo haría, pero esto:

LinkedListNode<MyNode> current = myList.First; 
while (current != null) 
{ 
    if (condition) // use current.Value to get the value 
    { 
     myList.AddLast(new MyNode()); 
    } 
    current = current.Next; 
} 

En lo que a mí consciente, eso es completamente seguro y predecible. Siempre puede pedirle a un nodo su próximo nodo. Si observa el nodo de cola y agrega otro, obtendrá el nuevo nodo de cola cuando solicite "siguiente".

Si eso no funciona, por favor denos más detalles sobre lo que está tratando de lograr.

+0

Totalmente seguro es un bucle de estiramiento, sin fin y OOM si el nuevo nodo coincide con la condición. –

1

Al iterar sobre una colección con la instrucción foreach, no puede modificarla. Por lo tanto, agregar elementos dará como resultado un error de compilación.

+0

usará el ciclo 'while' para resolver mi problema? –

+1

Puede usar un ciclo 'while' para recorrer la colección. No recibirá un error de compilación al hacer esto, pero tenga cuidado de no escribir un bucle infinito, lo que puede suceder si el nuevo 'MyNode()' cumple 'condición'. –

+3

* No * dará como resultado un error de compilación. El código proporcionado se compilará sin problemas. Lanzará una excepción en el momento de la ejecución. –

2

No, el objeto enumerador recuerda la versión interna de la colección propietaria. Después de que la colección se modifique, la versión cambiará, por lo que foreach fallará.

+0

+1 Para echar un vistazo con el reflector para ver cómo los enumeradores implementaban el cheque :) – Ani

0

Quizás podría agregarlos a una nueva lista. Luego, al final, fuera del foreach use .addrange() para agregar los nuevos a la lista original.

Cuestiones relacionadas