2009-09-15 8 views
1

Telle est la situation:Foreach tout en ajoutant des éléments à la collection en boucle

je navigue dans un code et je me demandais si la déclaration suivante prend une référence de la collection sélectionnée ou une copie avec laquelle il remplace l'original objet lorsque la boucle foreach se termine. Si le premier, va-t-il prendre les nouvelles pages trouvées et les rejoindre dans la boucle?

foreach(Page page in Pages) 
{ 
    page.AddRange(RetrieveSubPages(page.Id)); 
} 

Edit: Je suis désolé, j'ai fait une faute de frappe.

Il devrait être ceci:

foreach(Page page in pages) 
{ 
    pages.AddRange(RetrieveSubPages(page.Id)); 
} 

Ce que j'ai essayé de dire que si j'ajouter des objets à la collection de ENUMERE se joindre à elle ces objets dans le foreach?

Répondre

1

En réponse à votre question, il n'y a pas de copie.

Il crée un énumérateur et itère à travers la collection.Si la collection est modifiée pendant cette énumération se passe, dans le foreach lui-même, ou de manière asynchrone, vous obtiendrez une exception:

Une exception non gérée du type « System.InvalidOperationException » a eu lieu dans mscorlib.dll

Informations complémentaires : La collection a été modifiée l'opération d'énumération peut ne pas s'exécuter.

Vous pouvez, utiliser une collection temporaire et rejoindre les deux après, ou tout simplement ne pas utiliser un énumérateur.

for (int i = 0; i < pages.Count; i++) 
    { 
     test.AddRange(RetrieveSubPages(pages[i].Id)); 
    } 
1

foreach utilise un énumérateur. La collection sur laquelle vous effectuez une boucle en utilisant foreach doit implémenter IEnumerable (ou IEnumerable<T>). Ensuite, foreach appelle la méthode GetEnumerator de cette collection et utilise Enumerator pour parcourir la collection.

4

Dans la plupart des cas, foreach fonctionne avec la collection en cours (pas de clone explicite), et si vous essayez de modifier la collection en l'énumérant, l'énumérateur rompt avec une exception. Donc, si vous ajoutez Pages, attendez des problèmes.

5

Il semble que le code ne modifie pas la collection Pages, mais le contenu des objets dans les objets Page de la collection Pages. Le type Page ayant au moins une méthode de collecte.

En général, chaque collection implémente l'itération d'une manière qui lui convient, et devient généralement non modifiable en itérant, mais on pourrait implémenter une collection qui itère en prenant un instantané de lui-même.

Il n'y a aucun mécanisme pour détecter la sortie d'une boucle qui permettrait de prendre des mesures à ce moment-là (considérez comment cela interagirait avec les exceptions, cassez et retournez dans le corps de la boucle).

0

Je suis sûr que vous obtiendrez une exception levée se plaignant que la collection sous-jacente a été modifiée

1

Vous n'êtes pas en train de modifier la collection que vous énumérez, donc vous n'aurez aucun problème avec ce code.

Il est également inutile, si un clone de la collection est en cours d'énumération, car les objets contenus à la fois, collection et clone, sont toujours les mêmes (référence égale).

2

Je pense que la manière la plus sûre est la suivante:

Array<Page> newpages = new Array<Page>();  
foreach(Page page in pages) 
{ 
    newpages.AddRange(RetrieveSubPages(page.Id)); 
} 

pages.AddRange(newpages); 

Il faudrait étendre cela un peu si vous vouliez récursivité dans les sous-pages.

Questions connexes