Quel est le plus efficace boucle en c#
Il y a un certain nombre de façon différente de faire la même boucle simple si les éléments d'un objet en c#.
Cela m'a fait me demander si il n'y a aucune raison d'être la performance de l'informatique ou de la facilité d'utilisation, à utiliser sur le dessus de l'autre. Ou est-il juste en bas à la préférence personnelle.
Prendre un objet simple
var myList = List<MyObject>;
Permet de supposer l'objet est rempli et nous voulons effectuer une itération sur les éléments.
Méthode 1.
foreach(var item in myList)
{
//Do stuff
}
Méthode 2
myList.Foreach(ml =>
{
//Do stuff
});
Méthode 3
while (myList.MoveNext())
{
//Do stuff
}
Méthode 4
for (int i = 0; i < myList.Count; i++)
{
//Do stuff
}
Ce que je me demandais c'est de faire chaque de ces compilé vers le bas pour la même chose? est-il un clair avantage de performance pour l'utilisation de l'un sur l'autres?
ou est-ce juste en bas à la préférence personnelle, lors du codage?
Ai-je raté quelque?
- Vous pouvez toujours faire votre propre indice de référence, si vous voulez savoir comment ils diffèrent par leurs performances.
System.Diagnostics.StopWatch
est votre ami - voir ceci : forums.asp.net/t/1041090.aspx
- Vous avez manqué le do .. while(). En plus de cela, pourquoi ne pas compiler, et regardez les résultats dans ILDASM?
- Avez-vous de référence de la performance? Que faisaient vos résultats? En grande partie, à tout de votre propre logique va être le goulot d'étranglement, comment vous parcourez en grande partie négligeable, et parfois dictée par la situation. Peu un non-problème, purement académique question.
- Je me demandais si quelqu'un savait déjà, avant j'aller et de réinventer la roue..
- Certaines choses que vous devriez refaire.
- Je suppose que Parallèle.ForEach() serait plus rapide.
- Utiliser ce qui est plus lisible (pour vous) et ce que vous avez besoin. Donc, si vous souhaitez modifier la mise en œuvre des modifications ultérieures de l'
List<MyObject>
àIEnumerable<MyObject>
et l'utilisationforeach
ou si vous n'avez pas besoin d'indices, de toute façon. Je dois avouer que je n'ai jamais utiliséList.ForEach
dans les 10 dernières années pour plus de réponses sur DONC. - Question intéressante, après la lecture de Sam1 lien, il montre que, pour la et, tandis que les produits de la même MSIL donc, c'est essentiellement le même. Pour chacun, c'est plus lent, car il utilise l'interface IEnumerable et aussi quelques casting est nécessaire, car les types de savoir.
- Oui
Do { //do stuff } while(true)
est manquant, mais ce n'est functionaliy différents pour les autres boucles que ce sera toujours de faire au moins une itération de votre//Do stuff
quelle que soit la condition. - [foreach vs Linq] (geekswithblogs.net/BlackRabbitCoder/archive/2010/04/23/...)
- La question est étroitement liée stackoverflow.com/questions/6058390/when-to-use-which-for
- Remarque ce n'est pas un doublon de stackoverflow.com/q/6058390/50776 que @Jodrell souligné; le champ d'application de la que l'on comprend les extensions Parallèles, ce qui élargit la portée de la question (et modifie les réponses) grandement.
- c'est un bon point, le choix des extensions parallèles ou PLINQ pourrait avoir un effet significatif sur les performances. Cependant, les deux questions pourraient être fusionnés en un seul meilleure ressource.
- Pas vraiment, parce que les réponses de ici serait défaut; ils n'avaient pas fournir tous les détails concernant l'PLINQ. C'est un mauvais candidat pour la fusion.
Vous devez vous connecter pour publier un commentaire.
La réponse de la majorité du temps est il n'a pas d'importance. Le nombre d'éléments dans la boucle (encore que ce que l'on pourrait considérer comme un "grand" nombre d'éléments, par exemple dans les milliers) ne va pas avoir un impact sur le code.
Bien sûr, si vous l'identifier comme un goulot d'étranglement dans votre situation, par tous les moyens, de l'adresse, mais vous devez identifier le goulot d'étranglement de la première.
Cela dit, il y a un certain nombre de choses à prendre en considération à chaque approche, que je vais décrire ici.
Nous allons définir quelques choses d'abord:
laps de Temps.TicksPerSecond
sur ma machine = 10 000 000 deVoici quelques assistants qui sont nécessaires pour chaque test:
La
MyObject
classe:Une méthode pour créer un
List<T>
de n'importe quelle longueur deMyClass
instances:Une action à effectuer pour chaque élément de la liste (ce qui est nécessaire parce que la Méthode 2 utilise un délégué, et un appel doit être faite à quelque chose afin de mesurer l'impact):
Une méthode pour créer un
TextWriter
qui écrit sur un nullStream
(essentiellement des données de l'évier):Et nous allons fixer le nombre d'éléments à un million (1 000 000, qui devrait être suffisamment élevé pour faire valoir ce que de façon générale, ces toutes sur le même impact sur les performances):
Nous allons entrer dans les méthodes:
Méthode 1:
foreach
Le code suivant:
Compile vers le bas dans le texte suivant:
Il est tout à fait un peu là. Vous avez les appels de méthode (et il peut ou ne peut pas être contre la
IEnumerator<T>
ouIEnumerator
interfaces, comme le compilateur respecte canard-typage dans ce cas) et votre//Do stuff
est hissé dans que alors que la structure.Voici le test de mesure de la performance:
La sortie:
Méthode 2:
.ForEach
méthode surList<T>
Le code de la
.ForEach
méthode surList<T>
ressemble à quelque chose comme ceci:Noter que c'est fonctionnellement équivalente à la Méthode 4, à une exception près, le code qui est hissé dans le
for
boucle est passée en tant que délégué. Cela nécessite un déréférencement pour obtenir le code qui doit être exécuté. Bien que la performance des délégués s'est améliorée .NET 3.0 sur, que les frais généraux est là.Cependant, il est négligeable. Le test de mesure de la performance:
La sortie:
C'est fait ~7,5 secondes plus rapide que l'utilisation de la
foreach
boucle. Pas tout à fait surprenant, étant donné qu'il utilise directement accès au tableau au lieu d'utiliserIEnumerable<T>
.Rappelez-vous cependant, ce qui se traduit par 0.0000075740637 secondes par point d'être sauvé. C'est pas la peine pour les petites listes d'éléments.
Méthode 3:
while (myList.MoveNext())
Comme indiqué dans la Méthode 1, c'est exactement ce que le compilateur n' (avec l'ajout de la
using
déclaration, qui est bien pratique). Vous n'êtes pas gagner quoi que ce soit ici en déroulant le code vous-même, que le compilateur aurait autrement générer.Pour les coups de pied, nous allons le faire de toute façon:
La sortie:
Méthode 4:
for
Dans ce cas particulier, vous allez obtenir une vitesse, comme la liste de l'indexeur est d'aller directement dans le sous-tableau pour effectuer la recherche (c'est un détail d'implémentation, d'ailleurs, il n'y a rien à dire qu'il ne peut pas être une structure de l'arbre de la sauvegarde de la
List<T>
jusqu').La sortie:
Cependant le lieu où cette peut faire une différence est tableaux. Les tableaux peuvent être dénoué par le compilateur de traiter plusieurs éléments à la fois.
Au lieu de faire dix itérations d'un élément dans une dizaine de point de boucle, le compilateur peut se détendre en cinq itérations de deux éléments dans une dizaine d'élément de boucle.
Cependant, je ne suis pas positif ici que ce qui se passe réellement (je dois regarder le IL et la sortie de la compilation IL).
Voici le test:
La sortie:
Il convient de noter que out-of-the-box, Resharper propose une suggestion avec un refactoring pour changer le ci-dessus
for
déclarationsforeach
consolidés. Ce n'est pas de dire ce qui est juste, mais la base est de réduire le montant de la dette technique dans le code.TL;DR
Vous ne devriez pas être concerné par la performance de ces choses, à moins que des tests dans votre situation montre que vous avez un véritable goulot d'étranglement (et que vous aurez d'avoir d'énormes quantités d'éléments pour avoir un impact).
En général, vous devriez aller pour ce qui est plus facile à maintenir, dans ce cas, la Méthode 1 (
foreach
) est le chemin à parcourir.tl;dr
partie en elle-même ne devrait pas être, il est en fait très importante conclusion.tl;dr
, c'est important, et doit lire.tl;dr
. Je pourrait ne pas comprendre de quoitl;dr
veux dire.List<T>
mais unIList<T>
.En ce qui concerne le point final à la question "ai-je raté un?" oui et je sens que je m'en voudrais de ne pas mentionner ici, même si la question est assez vieux. Alors que ces quatre façons de le faire exécutera relativement la même quantité de temps leur est pas indiqué ci-dessus, qui court plus vite que tous d'entre eux, de façon très significative dans le fait que la taille de la liste qui est itéré augmente. Il serait exactement de la même manière que la dernière méthode, mais au lieu d'arriver .Comte dans la condition de contrôle de la boucle de vous affecter cette valeur à la variable avant la mise en place de la boucle et de l'utiliser à la place, vous laissant avec quelque chose comme ça
en le faisant de cette manière que votre seule recherche de la valeur d'une variable à chaque itération, plutôt que de résoudre le Comte ou propriétés de Longueur, ce qui est considérablement moins efficace.