Avec n'importe quel générique de mise en œuvre de IEnumerable la meilleure façon est:
//C#foreach(var item in listVariable){//do stuff}
Il y a une exception importante cependant. IEnumerable implique une surcharge de Courant() et MoveNext() qu'est ce que la boucle foreach est effectivement compilé dans.
Lorsque vous avez un simple tableau de structures:
//C#int[] valueTypeArray;for(int i=0; i < valueTypeArray.Length;++i){int item = valueTypeArray[i];//do stuff}
Est plus rapide.
Mise à jour
À la suite d'une discussion avec @Steven Sudit (voir les commentaires) je pense que mes conseils peuvent être obsolètes ou erronées, alors j'ai couru quelques tests:
//create a list to test withvar theList =Enumerable.Range(0,100000000).ToList();//time foreachvar sw =Stopwatch.StartNew();foreach(var item in theList){int inLoop = item;}Console.WriteLine("list foreach: "+ sw.Elapsed.ToString());
sw.Reset();
sw.Start();//time forint cnt = theList.Count;for(int i =0; i < cnt; i++){int inLoop = theList[i];}Console.WriteLine("list for : "+ sw.Elapsed.ToString());//now run the same tests, but with an arrayvar theArray = theList.ToArray();
sw.Reset();
sw.Start();foreach(var item in theArray){int inLoop = item;}Console.WriteLine("array foreach: "+ sw.Elapsed.ToString());
sw.Reset();
sw.Start();//time for
cnt = theArray.Length;for(int i =0; i < cnt; i++){int inLoop = theArray[i];}Console.WriteLine("array for : "+ sw.Elapsed.ToString());Console.ReadKey();
Donc, j'ai couru ce dans la version avec toutes les optimisations:
list foreach:00:00:00.5137506
list for:00:00:00.2417709
array foreach:00:00:00.1085653
array for:00:00:00.0954890
Et de déboguer sans optimisations:
list foreach:00:00:01.1289015
list for:00:00:00.9945345
array foreach:00:00:00.6405422
array for:00:00:00.4913245
De sorte qu'il semble assez cohérente, for est plus rapide que foreach et les tableaux sont plus rapide que le générique listes.
Cependant, c'est dans l'100 000 000 d'itérations et la différence est d'environ .4 d'une seconde entre la manière la plus rapide et la plus lente des méthodes. Sauf si vous êtes en train de faire une énorme performance critique des boucles, il n'est tout simplement pas la peine de s'inquiéter au sujet de.
La question était de savoir List<T>, pas de tableaux. Peu importe, je ne crois pas que foreach sur un tableau natif utilise IEnumerable, au moins pas dans le code optimisé, donc il n'y a pas de véritable speed-up. En fait, mon test montre foreach en ne prenant que les trois quarts du temps de for. Sudit - foreach boucles souffrent réellement de rapport for boucles une fois compilateur optimisation a été appliquée. Cependant j'ai fait quelques recherches autour - dans le cas d'un tableau foreach est optimisé pour exactement le même IL comme un for. Pour un List<T> le compilateur ne peut pas utiliser cette optimisation et la IL est un peu plus lent. On dirait que nous sommes tous les deux du mal (._. ) Je n'étais pas simplement parler de la théorie. J'ai écrit un court essai et il a couru. Si vous le souhaitez, je serais heureux de le déterrer et de le poster pour que vous puissiez voir comment cela fonctionne pour vous. Sudit - ouais, moi aussi. J'ai mis à jour la réponse avec les résultats. Permettez-moi de vous remercier pour la mettre dans le dur travail, mais je dois préciser que mes tests ont une différence essentielle: j'ai fait en sorte que les boucles passé chaque élément à une méthode externe. Sans cela, le compilateur est susceptible d'optimiser loin la cession entièrement. Je ne sais pas si cela représente pour le petit boost de vitesse, mais il pourrait facilement.
Comme Grauenwolf souligné ci-dessus VB ne compile pas car le lambda ne retourne pas une valeur. Normal boucle ForEach comme d'autres l'ont suggéré, est probablement la méthode la plus simple pour l'instant mais comme d'habitude il prend un bloc de code pour faire ce que C# peut le faire en une seule ligne.
Voici un banal pourquoi, par exemple, cela peut être utile: cela vous donne la possibilité de passer dans la boucle de la logique à partir d'une autre portée que celle où l'interface IEnumerable, de sorte que vous n'avez même pas à l'exposer si vous ne voulez pas.
Dire que vous avez une liste d'url relative chemins d'accès que vous souhaitez faire absolue:
Alors que vous pourriez appeler la fonction de cette manière:
var hostname ="myhost.com";var formatter = f =>String.Format("http://{0}{1}", hostname, f);IEnumerable<String> absolutePaths =Paths(formatter);
Vous donnant "http://myhost.com/about", "http://myhost.com/contact" etc. Évidemment, il ya de meilleures façons de faire dans ce spécfiques exemple, j'essaye juste de démontrer le principe de base.
Votre code VB ne fonctionne pas. VB prend uniquement en charge les fonctions anonymes dans cette version, vous devez attendre jusqu'à ce que VB10 avoir anonyme sous-routines. Vous avez raison, je n'ai pas le tester avant de poster. Pas étonnant de la documentation pour les expressions lambda en VB sont si rares; ils ne sont pas aussi utiles. Question évidente: Pourquoi s'embêter avec des rappels lorsque vous pouvez simplement faire un foreach? Vous êtes en supposant que l'interface IEnumerable et délégué sont de la même portée, mais malgré mon exemple simple, ils n'ont pas à l'être. Être en mesure de passer à une fermeture dans une fonction à partir d'une autre application peut être un très puissant motif de conception. Peut-être un exemple pourrait aider. Et s'il vous plaît commencer vos messages pour moi avec "@Steve" pour que je sois informé.
Sans le savoir la mise en œuvre interne de la liste, je pense que la meilleure façon de parcourir ce serait une boucle foreach. Parce que foreach utilise un IEnumerator à marcher sur la liste, c'est la liste de déterminer lui-même comment se déplacer d'un objet à l'objet.
Si la mise en œuvre interne était, disons, une liste liée, puis d'une simple boucle for serait un peu plus lent qu'un foreach.
Cela fait-il sens?
Oui, parce que la liste serait nécessaire de rechercher de façon linéaire pour chaque nouveau point, tandis qu'un itérateur sur il suffit de prendre un laissez-passer.
boucle foreach ou ForEach méthode, selon le communique votre intention plus clairement
Pourquoi foreach être plus lent? foreach se traduit par GetEnumerator(), MoveNext () () appelle ce qui n'est évidemment plus lent que l'incrémentation d'un indexeur et en sélectionnant à partir d'un tableau. Nous parlons de nanosecondes bien et n'est généralement pas de toutes les préoccupations. "for (index = objectListType.Count - 1; compteur >= 0; --count) { /* ... */ }" est le meilleur moyen, à mon avis, pour une raison. Il vous permet de supprimer des éléments pendant l'itération. Et si vous décidez de supprimer un élément de objectListType "objectListType.RemoveAt(index)", tout en boucle, vous n'aurez pas toute l'étrangeté ou la Modification-Tout-en-l'Énumération des exceptions. C'est bien que c'est performant.
J'ai peut-être raté quelque chose, mais le parcours d'une liste générique devrait être assez simple si vous utilisez mes exemples ci-dessous. La Liste des<> classe implémente l'IList et IEnumerable interfaces de sorte que vous pouvez facilement effectuer une itération à travers eux, fondamentalement, de la manière que vous voulez.
La manière la plus efficace serait d'utiliser une boucle for:
for(int i =0; i < genericList.Count;++i){//Loop body}
Vous pouvez également choisir d'utiliser une boucle foreach:
foreach(<insertTypeHere> o in genericList){//Loop body}
Pas besoin de <insertTypeHere>. Le compilateur de le faire pour vous avec var.
Pour C#:
Réponse pour VB.NET de Violet Ant:
foreach(var item in itemlist)
.OriginalL'auteur mbillard
Avec n'importe quel générique de mise en œuvre de IEnumerable la meilleure façon est:
Il y a une exception importante cependant. IEnumerable implique une surcharge de Courant() et MoveNext() qu'est ce que la boucle foreach est effectivement compilé dans.
Lorsque vous avez un simple tableau de structures:
Est plus rapide.
Mise à jour
À la suite d'une discussion avec @Steven Sudit (voir les commentaires) je pense que mes conseils peuvent être obsolètes ou erronées, alors j'ai couru quelques tests:
Donc, j'ai couru ce dans la version avec toutes les optimisations:
Et de déboguer sans optimisations:
De sorte qu'il semble assez cohérente,
for
est plus rapide queforeach
et les tableaux sont plus rapide que le générique listes.Cependant, c'est dans l'100 000 000 d'itérations et la différence est d'environ .4 d'une seconde entre la manière la plus rapide et la plus lente des méthodes. Sauf si vous êtes en train de faire une énorme performance critique des boucles, il n'est tout simplement pas la peine de s'inquiéter au sujet de.
List<T>
, pas de tableaux. Peu importe, je ne crois pas queforeach
sur un tableau natif utiliseIEnumerable
, au moins pas dans le code optimisé, donc il n'y a pas de véritable speed-up. En fait, mon test montreforeach
en ne prenant que les trois quarts du temps defor
.Sudit -
foreach
boucles souffrent réellement de rapportfor
boucles une fois compilateur optimisation a été appliquée. Cependant j'ai fait quelques recherches autour - dans le cas d'un tableauforeach
est optimisé pour exactement le même IL comme unfor
. Pour unList<T>
le compilateur ne peut pas utiliser cette optimisation et la IL est un peu plus lent. On dirait que nous sommes tous les deux du mal (._. )Je n'étais pas simplement parler de la théorie. J'ai écrit un court essai et il a couru. Si vous le souhaitez, je serais heureux de le déterrer et de le poster pour que vous puissiez voir comment cela fonctionne pour vous.
Sudit - ouais, moi aussi. J'ai mis à jour la réponse avec les résultats.
Permettez-moi de vous remercier pour la mettre dans le dur travail, mais je dois préciser que mes tests ont une différence essentielle: j'ai fait en sorte que les boucles passé chaque élément à une méthode externe. Sans cela, le compilateur est susceptible d'optimiser loin la cession entièrement. Je ne sais pas si cela représente pour le petit boost de vitesse, mais il pourrait facilement.
OriginalL'auteur Keith
Pour VB.NET:
OriginalL'auteur Brian G Swanson
C#
Anonyme délégués ne sont pas actuellement mis en œuvre dans VB.Net mais C# et VB.Net doit être capable de faire des lambdas:
C#
VB.Net
Comme Grauenwolf souligné ci-dessus VB ne compile pas car le lambda ne retourne pas une valeur. Normal boucle ForEach comme d'autres l'ont suggéré, est probablement la méthode la plus simple pour l'instant mais comme d'habitude il prend un bloc de code pour faire ce que C# peut le faire en une seule ligne.
Voici un banal pourquoi, par exemple, cela peut être utile: cela vous donne la possibilité de passer dans la boucle de la logique à partir d'une autre portée que celle où l'interface IEnumerable, de sorte que vous n'avez même pas à l'exposer si vous ne voulez pas.
Dire que vous avez une liste d'url relative chemins d'accès que vous souhaitez faire absolue:
Alors que vous pourriez appeler la fonction de cette manière:
Vous donnant
"http://myhost.com/about", "http://myhost.com/contact"
etc. Évidemment, il ya de meilleures façons de faire dans ce spécfiques exemple, j'essaye juste de démontrer le principe de base.Vous avez raison, je n'ai pas le tester avant de poster. Pas étonnant de la documentation pour les expressions lambda en VB sont si rares; ils ne sont pas aussi utiles.
Question évidente: Pourquoi s'embêter avec des rappels lorsque vous pouvez simplement faire un
foreach
?Vous êtes en supposant que l'interface IEnumerable et délégué sont de la même portée, mais malgré mon exemple simple, ils n'ont pas à l'être. Être en mesure de passer à une fermeture dans une fonction à partir d'une autre application peut être un très puissant motif de conception.
Peut-être un exemple pourrait aider. Et s'il vous plaît commencer vos messages pour moi avec "@Steve" pour que je sois informé.
OriginalL'auteur Adam Lassek
Sans le savoir la mise en œuvre interne de la liste, je pense que la meilleure façon de parcourir ce serait une boucle foreach. Parce que foreach utilise un IEnumerator à marcher sur la liste, c'est la liste de déterminer lui-même comment se déplacer d'un objet à l'objet.
Si la mise en œuvre interne était, disons, une liste liée, puis d'une simple boucle for serait un peu plus lent qu'un foreach.
Cela fait-il sens?
OriginalL'auteur Matt Hamilton
Cela dépend de votre demande:
foreach se traduit par GetEnumerator(), MoveNext () () appelle ce qui n'est évidemment plus lent que l'incrémentation d'un indexeur et en sélectionnant à partir d'un tableau. Nous parlons de nanosecondes bien et n'est généralement pas de toutes les préoccupations.
"for (index = objectListType.Count - 1; compteur >= 0; --count) { /* ... */ }" est le meilleur moyen, à mon avis, pour une raison. Il vous permet de supprimer des éléments pendant l'itération. Et si vous décidez de supprimer un élément de objectListType "objectListType.RemoveAt(index)", tout en boucle, vous n'aurez pas toute l'étrangeté ou la Modification-Tout-en-l'Énumération des exceptions. C'est bien que c'est performant.
OriginalL'auteur jfs
J'ai peut-être raté quelque chose, mais le parcours d'une liste générique devrait être assez simple si vous utilisez mes exemples ci-dessous. La Liste des<> classe implémente l'IList et IEnumerable interfaces de sorte que vous pouvez facilement effectuer une itération à travers eux, fondamentalement, de la manière que vous voulez.
La manière la plus efficace serait d'utiliser une boucle for:
Vous pouvez également choisir d'utiliser une boucle foreach:
<insertTypeHere>
. Le compilateur de le faire pour vous avecvar
.OriginalL'auteur Dan Herbert