2008-11-25 6 views
14

Possible en double:
LINQ equivalent of foreach for IEnumerable<T>Méthode d'extension LINQ existante similaire à Parallel.For?

Les méthodes d'extension LINQ pour IEnumerable sont très pratiques ... mais pas utile si tout ce que vous voulez faire est d'appliquer un certain calcul à chaque élément l'énumération sans rien retourner. Alors je me demandais si je manquais peut-être la bonne méthode, ou si elle n'existait pas vraiment car j'utiliserais plutôt une version intégrée si elle est disponible ... mais je n'en ai pas trouvé une :-)

J'aurais pu jurer qu'il existait une méthode .ForEach quelque part, mais je ne l'ai pas encore trouvée. En attendant, j'ai écrit ma propre version dans le cas où il est utile pour quelqu'un d'autre:

using System.Collections; 
using System.Collections.Generic; 

public delegate void Function<T>(T item); 
public delegate void Function(object item); 

public static class EnumerableExtensions 
{ 
    public static void For(this IEnumerable enumerable, Function func) 
    { 
     foreach (object item in enumerable) 
     { 
      func(item); 
     } 
    } 

    public static void For<T>(this IEnumerable<T> enumerable, Function<T> func) 
    { 
     foreach (T item in enumerable) 
     { 
      func(item); 
     } 
    } 
} 
utilisation

est:

myEnumerable.For<MyClass>(delegate(MyClass item) { item.Count++; });

+5

cf la réponse de Eric Lippert ici: http://blogs.msdn.com/ericlippert/archive/2009 /05/18/foreach-vs-foreach.aspx – Benjol

Répondre

15

Délestage un peu plus de lumière sur les raisons:

LINQ est fonctionnelle dans la nature. Il est utilisé pour interroger des données et renvoyer des résultats. Une requête LINQ ne doit pas modifier l'état de l'application (avec quelques exceptions comme la mise en cache). Parce que foreach ne renvoie aucun résultat, il n'a pas beaucoup d'utilisations qui n'impliquent pas de modifier l'état de quelque chose en plus de ce que vous lui passez. Et si vous avez besoin d'une méthode d'extension Foreach(), est facile à rouler.

Si, d'autre part, ce que vous voulez est de prendre une entrée et d'appeler une fonction sur chaque élément qui renvoie un résultat, LINQ fournit un chemin à travers sa méthode de sélection.

Par exemple, le code suivant appelle un délégué de fonction sur chaque élément dans une liste, retournant true si cet élément est positif:

static void Main(string[] args) 
    { 
     IEnumerable<int> list = new List<int>() { -5, 3, -2, 1, 2, -7 }; 
     IEnumerable<bool> isPositiveList = list.Select<int, bool>(i => i > 0); 

     foreach (bool isPositive in isPositiveList) 
     { 
      Console.WriteLine(isPositive); 
     } 

     Console.ReadKey();   
    } 
+2

Voir la confirmation à http://stackoverflow.com/questions/858978/lambda-expression-using-foreach-clause et http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach- vs-foreach.aspx –

3

La méthode ForEach sur List<T> fait cela. Vous pouvez envelopper votre collection dans une liste et ensuite utiliser cet appel, mais ce n'est pas vraiment une bonne chose à faire. On dirait que vous devrez rouler le vôtre.

+0

non, à moins que je ne manque quelque chose, il n'y a pas de méthode .ForEach –

+0

J'ai ajusté ma réponse comme ForEach est sur List <>. –

-1

Déjà discuté here et there. Je suis trop somnolent pour me souvenir, mais, fondamentalement, une méthode .ForEach dans une application à un seul thread est fonctionnellement équivalente à l'instruction foreach déjà existante. D'après ce que je comprends, la principale différence est qu'un ForEach pourrait être mis en parallèle mais cela introduirait trop facilement des comportements indésirables.

9

En fait, le cadre de Reactive Extensions de Microsoft Research a fait ajouter cette fonctionnalité. Dans l'assemblage System.Interactive, ils ont inclus une extension Run() et une extension Do() à IEnumerable<T>.

Do (action) exécute l'action sur chaque élément et le restitue.Ceci est utile pour ajouter l'enregistrement d'une requête linq par exemple:

var res = GetRandomNumbers(100).Take(10) 
     .Do(x => Console.WriteLine("Source -> {0}", x)) 
     .Where(x => x % 2 == 0) 
     .Do(x => Console.WriteLine("Where -> {0}", x)) 
     .OrderBy(x => x) 
     .Do(x => Console.WriteLine("OrderBy -> {0}", x)) 
     .Select(x => x + 1) 
     .Do(x => Console.WriteLine("Select -> {0}", x)); 

Cela se traduira par:

Source -> 96 
Where -> 96 
Source -> 25 
Source -> 8 
Where -> 8 
Source -> 79 
Source -> 25 
Source -> 3 
Source -> 36 
Where -> 36 
Source -> 51 
Source -> 53 
Source -> 81 
OrderBy -> 8 
Select -> 9 
9 
OrderBy -> 36 
Select -> 37 
37 
OrderBy -> 96 
Select -> 97 
97 

Run (action) est comme une boucle foreach, ce qui signifie que son pliage de la séquence qui exécute l'action.

Vous pouvez en lire davantage ici: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative.aspx

Le cadre Rx se trouve ici: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

+0

Je pense que c'est sous-estimé. – Den

Questions connexes