11
votes

Est-ce que ça va de réutiliser des collections iénumérables plus d'une fois?

Fondamentalement, je me demande s'il est correct d'utiliser une énumération plus d'une fois en code par la suite. Si vous vous cassez tôt ou non, l'énumération serait-elle toujours réinitialisée dans chaque cas foreach ci-dessous, ce qui nous donnait donc une énumération cohérente du début à la fin de la collection d'effets? XXX

Edit: La mise en œuvre des effetsRecursive est Ceci: xxx


4 commentaires

BTW J'ai ajouté la mise en œuvre d'effetsRecursive.


Méfiez-vous du rendement récursif. Il y a beaucoup de compilateur magique ici, créant ici des machines d'état. Si la structure de données est grande, cela pourrait être moins performant / plus complexe que prévu.


@Spender: Merci, y a-t-il une solution alternative que je peux utiliser?


@ERIC a répondu cela ci-dessous beaucoup plus éloquemment que je ne serais capable de.


5 Réponses :


0
votes

Tout dépend de la mise en œuvre du type de EffetsRecursive .


0 commentaires

6
votes

légal, oui. Si cela fonctionnera comme vous l'attend dépend de:

  • La mise en œuvre du ienumerable renvoyée par EffetsRecursive et s'il renvoie toujours le même ensemble;

  • si vous voulez énumérer le même jeu deux fois

    S'il renvoie un iNeumable qui nécessite un travail intensif, et cela ne cache pas les résultats en interne, vous devrez peut-être avoir besoin de .tolist () vous-même. Si cela met en cache les résultats, alors tolist () serait légèrement redondant mais probablement pas de mal.

    Aussi, si getenumerator () est implémenté dans une manière typique / appropriée (*), alors vous pouvez énumérer en toute sécurité un nombre de fois - chaque sera un nouvel appel à getenumerator () qui renvoie une instance nouvelle du ienumerator . Mais il pourrait être que dans certaines situations, il renvoie la même instance ienumerator déjà partiellement ou totalement énumérée, de sorte que tout dépend vraiment de l'utilisation spécifique de ce particulier iEnumerable .

    * Je suis sûr que je suis sûr que le même énumérateur multiple multiple est en réalité une violation du contrat implicite pour le modèle, mais j'ai vu des implémentations qui le font de toute façon.


0 commentaires

15
votes

Oui c'est légal à faire. Le modèle iEnumerable est destiné à prendre en charge plusieurs énumérations sur une source unique. Collections qui ne peuvent être énumérées qu'une seule fois devrait exposer ienumerator à la place.


0 commentaires

1
votes

Très probablement, oui. La plupart des implémentations de retour iEnumérables Un ienumerator frais qui commence au début de la liste.


0 commentaires

14
votes

Le code qui consomme de la séquence est très bien. Comme les points dépensiers sur le code qui produit l'énumération pourrait avoir des problèmes de performance si l'arbre est profond

Supposons au point le plus profond de votre arbre est quatre profond. penser à ce qui se passe sur les nœuds qui sont quatre de profondeur. Pour obtenir ce nœud, vous itérer la racine, qui appelle un itérateur, qui appelle un itérateur, qui appelle un itérateur, qui passe le nœud de retour au code qui passe le noeud de retour au code qui passe le dos de noeud ... Au lieu de remettre le nœud à l'appelant, vous avez fait une petite brigade de seau avec quatre gars, et ils sont piétinant les données autour d'un objet à avant qu'il ne soit finalement à la boucle qui le voulait. p>

Si l'arbre est seulement quatre de profondeur, probablement pas une grosse affaire. Mais supposons que l'arbre est dix mille éléments, et a un millier de noeuds formant une liste liée au sommet et les neuf mille nœuds restants sur le fond. Maintenant, quand vous itérer ces neuf mille nœuds chacun doit passer par mille itérateurs, pour un total de neuf millions d'exemplaires pour aller chercher neuf mille nœuds. (Bien sûr, vous avez probablement obtenu une erreur de débordement de pile et s'écrasent le processus.) P>

La façon de traiter ce problème si vous avez est de gérer la pile vous-même plutôt que de pousser les nouveaux itérateurs sur la pile p>

        foreach(var child in current.Effects.Reverse())


7 commentaires

@ERIC: Merci Eric, c'est une réponse incroyable. Je vais changer mes énumérations récursives comme celle-ci. Mais à la fin de votre exemple, votre exemple commencera avec le parent le plus haut des 9 000 articles, puis itérale à travers ces 9 000 articles de haut en bas, puis passez à travers l'autre haut la plupart des parents commençant après le premier haut le plus élevé. Parent Nous itérus comme premier élément, jusqu'à ce que nous finissions avec le plus haut niveau de gauche? C'est ce que vous voulez dire avec "l'arbre est traversé de haut en bas et à droite à gauche"?


@ERIC: BTW la ligne où vous avez dit "Stack.Push (this);" Renvoie l'instance actuelle aussi, non? Dans ma mise en œuvre, je veux seulement retourner les sous-effets de l'effet actuel sans elle-même. Puis-je simplement le supprimer? Je me sens comme cela causerait des problèmes dans la ligne Stack.Pop (). Qu'est-ce que tu penses?


@Joan: RE VOTRE PREMIER QUESTION: Supposons que l'arbre soit avec un enfant gauche B et un enfant droit C. Cet algorithme les donne dans l'ordre A, C, B. Nous avons d'abord mis un sur la pile. Ensuite, nous avons POP A et Mettez B et C sur la pile. Ensuite, nous avons POP C, puis nous avons POP B. B et C sont terminés à gauche au lieu de gauche à droite. Si vous voulez un, B, C, puis inversez la liste des enfants avant qu'ils ne soient poussés. Poussez A, Pop A, Push C, Poussez B, Pop B, Pop C, et maintenant nous avons un, B, C.


@Joan: Re votre deuxième question: Ce que vous pourriez faire est de repousser les enfants de "ceci" sur la pile avant que la boucle ne soit entrée pour obtenir le roulement de la balle.


@ Scientifique: merci pour ce truc Eric. Bien que maintenant, je reçois cette erreur de compilation pour tout ce qui concerne EffetsNoRecursive: "La déclaration de forach ne peut pas fonctionner sur des variables de type" groupe de méthodes "car" groupe de méthodes "ne contient pas de définition publique pour" Getenumerator "."


@Joan: Vous avez oublié les parenthèses. Le mien est une méthode, la vôtre est une propriété.


@ERIC: Merci Eric, je ne les ai même pas compris: o Maintenant, ça marche très bien.