2009-10-02 11 views
128

Duplicar posible:
Linq equivalent of foreach for IEnumerableestilo de LINQ "para cada"

¿Hay alguna sintaxis de estilo de LINQ para "para cada" operaciones?

Por ejemplo, agregue valores basados ​​en una colección a otra, ya existente:

IEnumerable<int> someValues = new List<int>() { 1, 2, 3 }; 

IList<int> list = new List<int>(); 

someValues.ForEach(x => list.Add(x + 1)); 

En lugar de

foreach(int value in someValues) 
{ 
    list.Add(value + 1); 
} 
+0

relacionada a esta pregunta, pero no es una víctima: http://stackoverflow.com/questions/858978/lambda-expression-using-foreach-clause – LukeH

+3

Ver también esta entrada del blog de Eric Lippert, con respecto a la justificación para no incluir 'ForEach' en el BCL: http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx – LukeH

+0

http://stackoverflow.com/questions/200574/linq-equivalent-of-foreach-for-ienumerable – aku

Respuesta

187

Utilizando el ToList() método de extensión es su mejor opción:

someValues.ToList().ForEach(x => list.Add(x + 1)); 

No hay un método de extensión en el BCL que implemente ForEach directamente.


Aunque no hay método de extensión en el BCL que hace esto, no es siendo una opción en el espacio de nombres System ... si se agrega Reactive Extensions a su proyecto:

using System.Reactive.Linq; 

someValues.ToObservable().Subscribe(x => list.Add(x + 1)); 

Esto tiene el mismo resultado final que el uso anterior de ToList, pero es (en teoría) más eficiente, porque transmite los valores directamente al delegado.

+4

Tenga en cuenta que esto no es ideal para una lista muy larga, ya que hace una copia de toda la lista antes de recorrerla. –

+6

Llamar a 'ToList' seguido de' ForEach' implica iterar a través de la colección original dos veces. Prefiero un bucle 'foreach' estándar todos los días: menos tipeo, más legible y mejor rendimiento: lista' foreach (var x en algunosValores) .Add (x + 1); ' – LukeH

+20

Para cualquiera que vea esto y crea que es un buena respuesta, no lo es. Es loco ineficiente. Vea la respuesta de Noldorin sobre la forma correcta de hacer las cosas. – Steve

2

No hay nada como eso en Linq estándar, pero hay un operador ForEach en MoreLinq.

67

Las clases Array y List<T> ya tienen métodos ForEach, aunque solo esta implementación específica. (Tenga en cuenta que el primero es static, por cierto).

No estoy seguro de que realmente ofrezca una gran ventaja sobre una declaración foreach, pero podría escribir un método de extensión para hacer el trabajo para todos los objetos IEnumerable<T>.

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

Esto permitiría que el código exacto que publicó en su pregunta funcione como usted lo desee.

+0

Gracias, está claro que podría escribir la extensión yo mismo. Solo quiero usar cosas integradas tanto como sea posible antes de hacer esto. –

+0

Sí, eso es justo. También me aseguro de no reinventar la funcionalidad de BCL. En este caso, no hay ninguno sin embargo. – Noldorin

+0

La clase Array no tiene un método ForEach :) pero hay una clase statşc "EnumerableExtensions" en el espacio de nombres Microsoft.Practices.ObjectBuilder2. tiene un método foreach para IEnumerable :) – ArgeKumandan

22

no hay nada incorporado, pero se puede crear fácilmente su propio método de extensión para hacerlo:

public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) 
{ 
    if (source == null) throw new ArgumentNullException("source"); 
    if (action == null) throw new ArgumentNullException("action"); 

    foreach (T item in source) 
    { 
     action(item); 
    } 
} 
12

La línea oficial de MS es "porque no es una operación funcional" (es decir, una operación con estado).

No se pudo hacer algo como:

list.Select(x => x+1) 

o si realmente lo necesita en una lista:

var someValues = new List<int>(list.Select(x => x+1)); 
+2

Tiene un punto sobre operaciones funcionales vs. estatales. Sin embargo, F # se diseñó como una longitud funcional, y tiene un método equivalente "ForEach". – Noldorin

1

no hay extensión LINQ ParaCada.Sin embargo, la clase List tiene un método ForEach en ella, si está dispuesto a usar el List directamente.

Por lo que vale la pena, la sintaxis estándar foreach le dará los resultados que desea y es probable que sea más fácil de leer:

foreach (var x in someValues) 
{ 
    list.Add(x + 1); 
} 

Si usted está convencido de que quieren una extensión del estilo de LINQ. es trivial implementar esto usted mismo.

public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action) 
{ 
    foreach (var x in @this) 
     action(x); 
} 
Cuestiones relacionadas