foreach vs someList.ForEach(){}
Il y a apparemment beaucoup de moyens pour effectuer une itération sur une collection. Curieux de savoir si il y a des différences, ou pourquoi vous devez utiliser un chemin sur les autres.
Premier type:
List<string> someList = <some way to init>
foreach(string s in someList) {
<process the string>
}
Autre Manière:
List<string> someList = <some way to init>
someList.ForEach(delegate(string s) {
<process the string>
});
Je suppose que sur le dessus de ma tête, qu'à la place du délégué anonyme j'utilise ci-dessus, vous auriez une réutilisables délégué, vous pouvez spécifier...
- Je suggère la lecture de Eric Lipperts blog "foreach" vs "ForEach"
Vous devez vous connecter pour publier un commentaire.
Il est important et utile, la distinction entre les deux.
Parce que .ForEach utilise un
for
de la boucle pour parcourir la collection, c'est valide (edit: avant .net 4.5 - la mise en œuvre changé et ils ont tous les deux les jeter):alors que
foreach
utilise un agent recenseur, ce n'est donc pas valide:tl;dr: Ne PAS copypaste ce code dans votre application!
Ces exemples ne sont pas les meilleures pratiques, ils sont juste pour démontrer les différences entre
ForEach()
etforeach
.Supprimer des éléments d'une liste dans un
for
boucle peut avoir des effets secondaires. Le plus commun est décrit dans les commentaires à cette question.Généralement, si vous êtes à la recherche pour supprimer plusieurs éléments d'une liste, vous voulez séparer la détermination des éléments à supprimer de la suppression effective de l'. Il ne gardez pas votre code compact, mais elle garantit que vous ne manquez pas tous les éléments.
List<T>.ForEach
lèvera une exception.Nous avons eu un peu de code ici (dans VS2005 et C#2.0) où le précédent ingénieurs sont sortis de leur manière d'utiliser
list.ForEach( delegate(item) { foo;});
au lieu deforeach(item in list) {foo; };
pour tout le code qu'ils ont écrit. par exemple, un bloc de code pour la lecture des lignes à partir d'un dataReader.Je ne sais toujours pas exactement pourquoi ils ont fait cela.
Les inconvénients de
list.ForEach()
sont:Il est plus prolixe en C# 2.0. Toutefois, en C# 3-delà, vous pouvez utiliser le bouton "
=>
" syntaxe pour faire bien laconique expressions.Il est moins familier. Les personnes qui ont à maintenir ce code me demande pourquoi vous l'avez fait de cette façon. Il m'a fallu un certain temps pour décider qu'il n'y avait aucune raison, sauf peut-être pour faire de l'écrivain judicieux (la qualité du reste du code sapé que). Il a également été moins lisible, avec le "
})
" à la fin du délégué bloc de code.Voir aussi le projet de Loi de Wagner livre "Effective C#: 50 Moyens Spécifiques pour Améliorer Votre C#", où il parle de pourquoi foreach est préféré à d'autres boucles comme pour la ou les boucles "while" - le point principal est que vous êtes de laisser le compilateur décider de la meilleure façon de construire la boucle. Si une future version du compilateur gère à utiliser une technique plus rapide, vous obtiendrez gratuitement en utilisant foreach et de reconstruction, plutôt que de changer votre code.
un
foreach(item in list)
construire vous permet d'utiliserbreak
oucontinue
si vous avez besoin de sortir de l'itération ou la boucle. Mais vous ne pouvez pas modifier la liste à l'intérieur d'une boucle foreach.Je suis surpris de voir que
list.ForEach
est légèrement plus rapide. Mais ce n'est probablement pas une raison valable pour l'utiliser dans tout , que serait prématuré d'optimisation. Si votre application utilise une base de données ou un service web, pas de contrôle de la boucle, est presque toujours va être où le temps passe. Et avez-vous comparé par rapport à unfor
boucle de trop? Lelist.ForEach
pourrait être plus rapide en raison de l'aide qu'à l'interne etfor
boucle sans l'emballage serait encore plus rapide.Je suis en désaccord que le
list.ForEach(delegate)
version est "la plus fonctionnelle" de manière significative. Il passe d'une fonction à une fonction, mais il n'y a pas de grande différence dans le résultat ou le programme de l'organisation.Je ne pense pas que
foreach(item in list)
"dit exactement comment vous voulez qu'il fait" - unfor(int 1 = 0; i < count; i++)
boucle n'est qu'unforeach
boucle laisse le choix de contrôler jusqu'à le compilateur.Mon sentiment est sur un nouveau projet, d'utiliser
foreach(item in list)
pour la plupart des boucles pour adhérer à l'usage commun et pour des raisons de lisibilité, et l'utilisationlist.Foreach()
uniquement pour les blocs courts, quand vous pouvez faire quelque chose de plus élégamment ou de manière compacte avec le C# 3 "=>
" de l'opérateur. Dans de tels cas, il peut y avoir une extension LINQ méthode est plus spécifique queForEach()
. Voir siWhere()
,Select()
,Any()
,All()
,Max()
ou une des nombreuses autres méthodes LINQ n'est pas déjà faire ce que vous voulez à partir de la boucle.Pour le fun, j'ai sauté de la Liste de réflecteur et c'est le C# résultant:
De même, la MoveNext dans Énumérateur qui est utilisé par la foreach est-ce:
La Liste.ForEach est beaucoup plus réduite que MoveNext - beaucoup moins de traitement sera le plus souvent JIT en quelque chose d'efficace..
En outre, foreach() va allouer un nouvel agent Recenseur n'importe quoi. La GC est un ami, mais si vous faites la même foreach à plusieurs reprises, cela va faire plus d'objets jetables, par opposition à la réutilisation de la même délégué - MAIS - c'est vraiment une frange de cas. En utilisation normale, vous verrez que peu ou pas de différence.
Je sais que les deux obscur-ish choses qui les rendent différents. Aller moi!
Tout d'abord, il y a le classique bug de faire un délégué pour chaque élément de la liste. Si vous utilisez le mot-clé foreach, tous vos délégués peuvent se référant au dernier élément de la liste:
La Liste.ForEach méthode n'ont pas ce problème. L'élément actuel de l'itération est passé par valeur, comme un argument à l'extérieur lambda, et puis l'intérieur lambda correctement saisit cet argument dans sa propre fermeture. Le problème est résolu.
(Malheureusement je crois ForEach est un membre de la Liste, plutôt qu'une extension de la méthode, mais il est facile de définir vous-même si vous disposez de cette installation sur toute énumérable type.)
Deuxièmement, l'approche de la méthode ForEach a une limitation. Si vous êtes à la mise en œuvre de IEnumerable en utilisant les taux de retour, vous ne pouvez pas faire un taux de retour à l'intérieur de la lambda. Donc à parcourir les éléments dans une collection pour obtenir le retour des choses n'est pas possible par cette méthode. Vous aurez à utiliser le mot-clé foreach et de travailler autour de la fermeture, le problème manuellement en faisant une copie de la boucle de courant de valeur à l'intérieur de la boucle.
Plus ici
foreach
est "fixe" en C# 5. stackoverflow.com/questions/8898925/...Je suppose que le
someList.ForEach()
appel pouvait être facilement parallélisable alors que la normaleforeach
n'est pas facile à exécuter en parallèle.Vous pouvez facilement exécuter plusieurs délégués sur les différents cœurs, qui n'est pas facile à faire avec un normal
foreach
.Juste mes 2 cents
Vous pouvez nommer le délégué anonyme 🙂
Et vous pouvez écrire le deuxième:
Que je préfère, et permet d'économiser beaucoup de la dactylographie.
Que Joachim dit, le parallélisme est plus facile à appliquer à la deuxième forme.
Derrière les coulisses, le délégué anonyme est transformé en une véritable méthode de sorte que vous pourriez avoir des frais généraux avec le deuxième choix si le compilateur n'a pas choisi de l'inclure la fonction. En outre, toutes les variables locales référencées par le corps de l'anonyme délégué exemple des changements dans la nature en raison de compilateur astuces pour cacher le fait qu'elle sera compilé pour une nouvelle méthode. Plus d'infos ici sur la façon dont C# est-ce à la magie:
http://blogs.msdn.com/oldnewthing/archive/2006/08/04/688527.aspx
Liste.ForEach() est considérée comme la plus fonctionnelle.
List.ForEach()
dit ce que vous voulez faire.foreach(item in list)
également dit exactement comment vous voulez qu'il fait. Cela laisseList.ForEach
libre de changer la mise en œuvre de la comment part dans l'avenir. Par exemple, dans un futur hypothétique version de .Net peut toujours courirList.ForEach
en parallèle, sous l'hypothèse que, à ce point, tout le monde a un nombre de cœurs de processeur qui sont généralement assis au ralenti.D'autre part,
foreach (item in list)
vous donne un peu plus de contrôle sur la boucle. Par exemple, vous savez que les articles seront répétées dans un ordre séquentiel, et vous pourriez facilement percer dans le milieu si un élément qui répond à une certaine condition.L'ensemble de la ForEach champ d'application (fonction de délégué) est considéré comme une seule ligne de code (l'appel de la fonction), et vous ne pouvez pas définir des points d'arrêt ou une étape dans le code. Si une exception non gérée se produit le bloc entier est marqué.
La deuxième façon, vous a montré utilise une extension de la méthode à exécuter la méthode du délégué pour chacun des éléments de la liste.
De cette façon, vous avez un autre délégué (=méthode) appel.
En outre, il ya la possibilité d'itérer la liste avec un pour boucle.
Une chose à se méfier de l'est comment sortir du Générique .ForEach méthode - voir cette discussion. Bien que le lien semble dire que c'est le plus rapide. Pas sûr pourquoi vous pourriez penser qu'ils seraient l'équivalent d'une fois compilé...
Le ForEach fonction membre de la classe générique List.
Que j'ai créé à la suite de l'extension de reproduire le code interne:
Donc à la fin, nous utilisons une normale foreach (ou une boucle pour si vous voulez).
Sur l'autre main, à l'aide d'une fonction de délégué est juste une autre façon de définir une fonction, ce code:
est équivalent à:
ou à l'aide de labda expressions: