57 votes

LINQ + Foreach vs Foreach + Si

J'ai besoin d'itérer sur une Liste d'objets, de faire quelque chose seulement pour les objets qui ont une propriété booléenne définie sur true. Je me débats entre ce code

foreach (RouteParameter parameter in parameters.Where(p => p.Condition))
{ //do something }

et ce code

foreach (RouteParameter parameter in parameters)
{ 
  if !parameter.Condition
    continue;
  //do something
}

Le premier code est évidemment plus propre, mais je suppose qu'il en va de la boucle sur la liste deux fois - une fois pour la requête et une fois pour le foreach. Ce ne sera pas une liste énorme donc je ne suis pas trop inquiet au sujet de la performance, mais l'idée de la boucle deux fois des bugs moi.

Question: Est-il propre/jolie façon d'écrire cela sans boucle deux fois?

130voto

Eric Lippert Points 300275

Jon Skeet ne sont, parfois, un live-action LINQ de démonstration pour expliquer comment cela fonctionne. Imaginez que vous avez trois personnes sur scène. Sur la gauche, nous avons un gars qui a un jeu de cartes mélangé. Dans le milieu, nous avons un gars qui ne fait que passer le long de cartons rouges, et sur la droite, nous avons un gars qui veut des cartes.

Le gars sur la droite attise le gars dans le milieu. Le gars dans le milieu pousse le gars sur la gauche. Le gars sur la gauche, les mains, le gars au moyen d'une carte. Si elle est noire, le gars dans le milieu le jette sur le sol et pousse à nouveau jusqu'à ce qu'il obtienne une carte rouge, qu'il remet à la personne sur la droite. Puis le gars sur la droite attise le gars dans le milieu nouveau.

Cela continue jusqu'à ce que le gars sur la gauche, à court de cartes.

Le pont n'a pas été passée au travers du début à la fin plus d'une fois. Cependant, à la fois le gars sur la gauche et le gars dans le milieu traitées 52 cartes, et le gars sur la droite traitées 26 cartes. Il y avait un total de 52 + 52 + 26 opérations sur les cartes, mais le pont était seulement en boucle à travers une fois.

Votre "LINQ" et la version "continuer" version sont la même chose; si vous aviez

foreach(var card in deck)
{
    if (card.IsBlack) continue;
    ... use card ...

puis il y a 52 opérations d'extraction de chaque carte de la pioche, 52 opérations de test pour voir si chaque carte est noire, et 26 les opérations qui agissent sur la carte rouge. Même chose exactement.

37voto

Johannes Rudolph Points 19845

La plupart des opérateurs Linq comme Where sont en place pour soutenir reportés et paresseux exécution. Dans votre exemple, la liste va être itéré qu'une seule fois, car l'énumérateur assis derrière le IEnumerable retourné par Where énumérer la liste jusqu'à trouver un élément correspondant au prédicat, cède et ne reprendra que lorsqu'il est demandé à l'élément suivant.

Dans une perspective de code, je préfère la variante où, bien qu'on puisse soutenir vous pouvez déclarer un local de l' parameters.Where(p => p.Condition).

Jon Skeet est Edulinq série est fortement recommandé, la lecture de certains morceaux de ce devrait vous aider à comprendre opérateurs LINQ.

27voto

StriplingWarrior Points 56276

En fait, ce n'est pas "en boucle deux fois." L' .Where clause utilise exécution différée. En d'autres termes, pratiquement aucun travail n'est effectué lorsque vous appelez .Where, mais lorsque vous parcourez le résultat, il va itérer sur la liste d'origine et seulement passer à travers les éléments qui correspondent à votre état de santé. Si vous pensez en termes de la façon dont le code est exécuté, vous êtes effectivement le faire:

Func<Parameter, bool> matchesCondition = p => p.Condition;
foreach(var parameter in parameters)
{
    if(matchesCondition(parameter))
    {
        ...
    }
}

Comme une question de style, personnellement, je préfère quelque chose de plus comme:

var matchingParameters = parameters.Where(p => p.Condition);
foreach(var parameter in matchingParameters)
{
}

-3voto

Carlos V Points 11

Je préfère ça:

 theList.Where(itm => itm.Condition).ToList().ForEach(itmFE => { itmFe.DoSomething(); }); 
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X