2010-08-08 18 views
5

Posso aggiungere in modo sicuro nodi al contenitore LinkedList all'interno dell'istruzione foreach? C'è qualche differenza se ho usato il ciclo while? Oppure non è mai permesso e può causare alcuni problemi?Aggiunta di nodi a LinkedList <T> in foreach

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

Volontà sempre lavoro?

risposta

6

Non è possibile modificare una raccolta mentre si enumera su di essa.

Dal docs for LinkedList<T>.GetEnumerator:

Un enumeratore rimane valido finché la collezione rimane invariato. Se le modifiche vengono apportate alla raccolta, come aggiungere, modificare o eliminare elementi , l'enumeratore è irrecuperabilmente invalidato e il suo comportamento non è definito.

In pratica credo che lancerà sempre un InvalidOperationException, nonostante il comportamento ufficialmente non definito.

EDIT: ti ha chiesto in un commento se un ciclo while aiuterebbe ... un ciclo durante l'utilizzo GetEnumerator/MoveNext/Current no, ma questo:

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

Per quanto mi consapevole, è del tutto sicuro e prevedibile. Puoi sempre chiedere a un nodo il suo prossimo nodo. Se ti capita di guardare il nodo di coda e aggiungerne un altro, otterrai il nuovo nodo di coda quando chiederai "next".

Se ciò non aiuta, forniscici maggiori dettagli su ciò che stai cercando di ottenere.

+0

Completamente sicuro è un tratto, un ciclo infinito e OOM se il nuovo nodo corrisponde alla condizione. –

1

Durante l'iterazione su una raccolta con la dichiarazione foreach, non è possibile modificarla. Pertanto, l'aggiunta di elementi comporterà un errore del compilatore.

+0

utilizzerà il ciclo "while" per risolvere il problema? –

+1

È possibile utilizzare un ciclo 'while' per eseguire il loop sulla raccolta. Non si riceve un errore del compilatore quando si esegue questa operazione, ma si faccia attenzione a non scrivere un ciclo infinito - cosa che può succedere se il nuovo 'MyNode()' soddisfa 'condizione'. –

+3

* * non comporterà un errore del compilatore. Il codice fornito verrà compilato senza problemi. Genera un'eccezione al momento dell'esecuzione. –

2

No, l'oggetto enumeratore ricorda la versione interna della collezione proprietaria. Dopo la raccolta viene modificata - la versione è cambiata, quindi foreach avrà esito negativo.

+0

+1 Per sbirciare con il riflettore per vedere come gli enumeratori stavano implementando il controllo :) – Ani

0

Forse potresti aggiungerli a una nuova lista. Quindi, alla fine, all'esterno dello foreach utilizzare .addrange() per aggiungere i nuovi all'elenco originale.

Problemi correlati