2008-11-25 8 views
14

Duplicar posible:
LINQ equivalent of foreach for IEnumerable<T>Método de extensión LINQ existente similar a Parallel.For?

métodos de extensión

El LINQ para IEnumerable son muy útiles ... pero no es tan útil si lo que quieres hacer es aplicar algún cálculo para cada elemento de la enumeración sin devolver nada. Así que me preguntaba si quizás me estaba perdiendo el método correcto, o si realmente no existe, ya que prefiero usar una versión incorporada si está disponible ... pero no he encontrado una :-)

Podría haber jurado que había un método .ForEach en alguna parte, pero aún no lo he encontrado. Mientras tanto, he escrito mi propia versión en caso de que sea útil para cualquier otra persona:

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); 
     } 
    } 
} 

uso es:

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

+5

cf respuesta de Eric Lippert aquí: http://blogs.msdn.com/ericlippert/archive/2009 /05/18/foreach-vs-foreach.aspx – Benjol

Respuesta

15

Arrojando un poco más de luz sobre por qué:

LINQ es funcional en la naturaleza. Se usa para consultar datos y devolver resultados. Una consulta LINQ no debe alterar el estado de la aplicación (con algunas excepciones como el almacenamiento en caché). Debido a que foreach no arroja ningún resultado, no tiene muchos usos que no impliquen alterar el estado de algo además de lo que le está pasando. Y si necesita un método de extensión Foreach(), es fácil de implementar.

Si, por otro lado, lo que desea es tomar entrada y llamar a una función en cada elemento que devuelve un resultado, LINQ proporciona un camino a través de su método de selección.

Por ejemplo, el código siguiente llama a un delegado la función en cada elemento de una lista, volviendo cierto si ese elemento es positivo:

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

Consulte la confirmación en http://stackoverflow.com/questions/858978/lambda-expression-using-foreach-clause y http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach- vs-foreach.aspx –

3

El método ParaCada en List<T> hace esto. Puede envolver su colección en una lista y luego usar esa llamada, pero eso no es realmente algo bueno que hacer. Parece que tendrás que hacer tu propio.

+0

no, a menos que me falta algo, no hay un método .ForEach –

+0

Ajusté mi respuesta ya que ForEach está en la Lista <>. –

-1

Ya discutido here y there.

Soy demasiado soñoliento para recordar pero, básicamente, un método .ForEach en una aplicación de un único hilo es funcionalmente equivalente al enunciado foreach ya existente. Por lo que entiendo, la principal diferencia es que un ForEach podría ser paralizado, pero eso introduciría comportamientos no deseados con demasiada facilidad.

9

En realidad, el marco extensiones reactivas de Microsoft Research has agregado esta funcionalidad. En el ensamblaje System.Interactive, han incluido extensiones Run() y Do() en IEnumerable<T>.

Do (acción) ejecutará la acción en cada elemento y lo devolverá.Esto es útil para añadir el registro a una consulta linq por ejemplo:

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)); 

Esto resultará en:

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 (acción) es como un bucle foreach, lo que significa su plegado de la secuencia que ejecuta la acción

Puede leer más sobre esto aquí: http://community.bartdesmet.net/blogs/bart/archive/2009/12/26/more-linq-with-system-interactive-the-ultimate-imperative.aspx

El marco Rx se puede encontrar aquí: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx

+0

Creo que esto es poco apreciado. – Den

Cuestiones relacionadas