Je programme depuis maintenant un bon moment, que ce soit sur la plateforme .Net (pouah, déjà tout ce temps) que sur VB6 ou même un peu de C ...
Mais en ce moment, je suis en train de m'appercevoir que bon nombre de personne ont un petit problème avec les itérations de types for.
For et For Each, ici en VB, sont deux itérations relativement semblables. A tel point que bien souvent, on prend l'habitude d'utiliser l'une plus que l'autre. Et souvent, on prend la mauvaise habitude. Je m'explique.
Que se soient de vieux développeur ou des jeunes, il y en a qui, quelque soit la situaton passent par l'itération For Each, sans se demander si For i as integer, comme on a coutume de voir, ne ferait pas le même boulot mais un peu plus vite. J'en suis même arrivé à douter mais non
J'ai donc écrit vite fait un petit 'bench' dans le train pour vérifier quand même.
Donc c'est bien simple. Je rempli une List(of myItem) avec 10 000 000 d'instances. myItem est un type tout simple, avec seulement une propriété Value de type string.
Ensuite, je lance 5 fois la même série d'itérations, c'est-à-dire une fois For Each, une fois For i as integer, et je mesure le temps d'éxécution à l'aide de la classe Stopwatch (tutoriel de mon ami Ronald Vasseur).
| Itération |
For Each |
For i |
| 1 |
154 |
112 |
| 2 |
151 |
110 |
| 3 |
171 |
119 |
| 4 |
157 |
112 |
| 5 |
157 |
111 |
Je pense que le résultat est sans appel. Le For Each peut se révéler presque 1 fois et demie plus lent que le For i as integer.
L'explication est même relativement simple. Si vous regardez de plus près le fonctionnement de For Each, vous verrez qu'il ne fonctionne avec les implémentations d'IEnumerable. Mais IEnumerable, c'est compliqué, du moins à l'exécution.
Il faut d'abord récupérer une instance de l'énumérateur, ensuite à chaque boucle, se déplacer à l'élément suivant via une méthode, et ensuite récupérer l'élément en cours dans l'énumérateur.
Deux appels de méthodes à chaque passage, qui elles même peuvent effectuer des tâches supplémentaires de contrôle ... donc une perte de temps conséquente. Par contre, on récupère directement une instance de notre objet de liste.
For i as integer, elle ne fait qu'incrémenter un compteur et vérifier que celui-ci ne dépasse pas la limite fixée. Dans le cas présent, il y a aussi appel au 'seter' de la propriété Item de List, mais ça ne fait plus qu'un appel.
Donc, au vu de ces résultats et de ces quelques explications, je ne saurais que vous conseiller de réfléchir juste un peu plus lors de l'utilisation de For Each, qui se révèle dans certains cas incontournable (Dictionary(of T)), mais le plus souvent inutile. Si vous regardez la MSDN à propos de l'interface IEnumerable, vous verez en détail le fonctionnement et surtout que, ce n'est qu'un exemple, mais l'implémentation ressemble étrangement à un For i as integer lol
Bonne prog