web-dev-qa-db-fra.com

Exécution d'une certaine action pour tous les éléments d'un Enumerable <T>

J'ai un Enumerable<T> et je cherche une méthode qui me permet d'exécuter une action pour chaque élément, un peu comme Select mais ensuite pour les effets secondaires. Quelque chose comme:

string[] Names = ...;
Names.each(s => Console.Writeline(s));

ou 

Names.each(s => GenHTMLOutput(s));   
// (where GenHTMLOutput cannot for some reason receive the enumerable itself as a parameter)

J'ai essayé Select(s=> { Console.WriteLine(s); return s; }), mais cela n'imprimait rien.

42
Daniel Magliola

Un moyen rapide et facile d'obtenir ceci est:

Names.ToList().ForEach(e => ...);
48
Jay Bazuzi

Vous recherchez le ForEach toujours insaisissable qui n'existe actuellement que dans la collection générique List. Il existe de nombreuses discussions en ligne sur le point de savoir si Microsoft devrait ou non ajouter ceci en tant que méthode LINQ. Actuellement, vous devez rouler le vôtre:

public static void ForEach<T>(this IEnumerable<T> value, Action<T> action)
{
  foreach (T item in value)
  {
    action(item);
  }
}

Alors que la méthode All() fournit des capacités similaires, son cas d’utilisation sert à effectuer un test de prédicat sur chaque élément plutôt qu’une action. Bien sûr, il peut être persuadé d’effectuer d’autres tâches, mais cela change quelque peu la sémantique et rendrait plus difficile l’interprétation de votre code par d’autres (c’est-à-dire que cette utilisation de All() pour un test de prédicat ou une action?).

18
Jeff Yates

Malheureusement, il n'y a pas de moyen intégré de faire cela dans la version actuelle de LINQ. L'équipe de la structure a négligé d'ajouter une méthode d'extension .ForEach. Il y a une bonne discussion à ce sujet en ce moment sur le blog suivant. 

http://blogs.msdn.com/kirillosenkov/archive/2009/01/31/foreach.aspx

C'est assez facile d'en ajouter un cependant.

public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action) {
  foreach ( var cur in enumerable ) {
    action(cur);
  }
}
6
JaredPar

Vous ne pouvez pas le faire tout de suite avec LINQ et IEnumerable - vous devez implémenter votre propre méthode d'extension ou transtyper votre énumération en un tableau avec LINQ, puis appeler Array.ForEach ():

Array.ForEach(MyCollection.ToArray(), x => x.YourMethod());

Veuillez noter qu'en raison de la manière dont les types de valeur et les structures fonctionnent, si la collection est d'un type valeur et que vous modifiez les éléments de la collection de cette manière, cela n'aura aucun effet sur les éléments de la collection d'origine.

4
Tamas Czinege

Étant donné que LINQ est conçu pour être une fonction de requête et non une fonction de mise à jour, vous ne trouverez pas d’extension permettant l’exécution de méthodes sur IEnumerable <T>, car elle vous permettrait d’exécuter une méthode (avec éventuellement des effets secondaires). Dans ce cas, vous pouvez aussi bien vous en tenir à

foreach (nom de chaîne dans Noms)
Console.WriteLine (name);

2
Peter Morris

Eh bien, vous pouvez également utiliser le mot clé foreach standard, il vous suffit de le formater dans un oneliner:

foreach(var n in Names.Where(blahblah)) DoStuff(n);

Désolé, je pense que cette option mérite d'être ici :)

1
Serge Shultz

Il existe une méthode ForEach en dehors de la liste. Vous pouvez convertir Enumerable to List en appelant la méthode .ToList (), puis appeler la méthode ForEach en dehors de cela. 

Alternativement, j'ai entendu parler de personnes définissant leur propre méthode ForEach à partir de IEnumerable. Cela peut être accompli en appelant essentiellement la méthode ForEach, mais en l'enveloppant dans une méthode d'extension:

public static class IEnumerableExtensions
{
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> _this, Action<T> del)
    {
        List<T> list = _this.ToList();
        list.ForEach(del);
        return list;
    }
}
0
David Morton

Utiliser Parallel Linq:

Names.AsParallel (). ForAll (name => ...)

0
Chris Xue