2009-10-02 16 views
128

Powiel możliwe:
Linq equivalent of foreach for IEnumerableLINQ stylu "dla każdego"

Czy istnieje styl składni LINQ dla "dla każdego" operacji?

Na przykład, dodanie wartości na podstawie jednego zbioru do innego, już istniejącego:

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

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

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

Zamiast

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

związane z tym pytaniem, ale nie dość dupe: http://stackoverflow.com/questions/858978/lambda-expression-using-foreach-clause – LukeH

+3

Zobacz też ten wpis na blogu Eric Lippert, dotyczące racjonalne uzasadnienie braku włączenia słowa "ForEach" w 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 -iennotable – aku

Odpowiedz

187

Używanie ToList() metoda rozszerzenie jest najlepszym rozwiązaniem:

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

Nie ma metody rozszerzenia w BCL, która implementuje ForEach bezpośrednio.


Chociaż nie ma metodę rozszerzenia w BCL który to robi, nie jest jeszcze opcja w przestrzeni nazw System ... jeśli dodać Reactive Extensions do projektu:

using System.Reactive.Linq; 

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

Ma to taki sam efekt końcowy jak powyższe użycie ToList, ale jest (teoretycznie) bardziej wydajne, ponieważ przesyła wartości bezpośrednio do uczestnika.

+4

Pamiętaj, że nie jest to idealne rozwiązanie dla bardzo długiej listy, ponieważ tworzy kopię całej listy przed przejściem przez nią. –

+6

Wywołanie 'ToList', po którym następuje' ForEach', polega na dwukrotnym iterowaniu przez oryginalną kolekcję. Wolałbym standardową pętlę foreach każdego dnia: mniej pisania, bardziej czytelną i lepszą wydajność: 'foreach (var x in someValues) list.Add (x + 1);' – LukeH

+20

Dla każdego, kto to widzi i myśli, że jest dobra odpowiedź, nie jest. To szalone nieefektywne. Zobacz odpowiedź Noldorina na poprawny sposób robienia rzeczy. – Steve

2

Nie ma czegoś takiego w standardowym Linq, ale istnieje operator ForEach w MoreLinq.

67

Klasy Array i List<T> mają już metody ForEach, ale tylko ta konkretna implementacja. (Zauważ, że ten pierwszy to static, nawiasem mówiąc).

Nie jestem pewien, czy to naprawdę daje wielką przewagę nad stwierdzeniem foreach, ale można napisać metodę rozszerzenia, aby wykonać zadanie dla wszystkich obiektów IEnumerable<T>.

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

Pozwoliłoby to na to, aby dokładny kod, który opublikowałeś w swoim pytaniu, działał tak, jak chcesz.

+0

Dzięki, To jasne, że sam mogłem napisać rozszerzenie. Po prostu chcę użyć wbudowanych rzeczy tak daleko, jak to możliwe, zanim to zrobię. –

+0

Tak, to całkiem fair. Upewniam się też, że również nie odkrywam funkcjonalności BCL. W tym przypadku jednak nie ma. – Noldorin

+0

Klasa tablicy nie ma metody ForEach :), ale istnieje klasa statşc "EnumerableExtensions" w przestrzeni nazw Microsoft.Practices.ObjectBuilder2. ma on metodę foreach dla IEnumerable :) – ArgeKumandan

22

Nie ma nic wbudowany, ale łatwo można stworzyć własną metodę rozszerzenia to zrobić:

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

Oficjalna linia MS jest „ponieważ nie jest to funkcjonalne działanie” (to znaczy, że jest to działanie stanowe).

nie mógłby zrobić coś takiego:

list.Select(x => x+1) 

czy naprawdę trzeba go w formie listy:

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

Masz punkt dotyczący operacji funkcjonalnych vs stanowych. Jednakże F # został zaprojektowany jako długość funkcjonalna i ma równoważną metodę "ForEach". – Noldorin

1

Nie ma rozszerzenie LINQ ForEach.Jednak klasa List ma metodę ForEach, jeśli chcesz bezpośrednio użyć List.

Na co warto, a średnia składnia foreach daje pożądane wyniki i to chyba łatwiejsze do odczytania:

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

Jeśli nieugięty chcesz rozszerzenie styl Linq. jest to łatwe do zrealizowania samodzielnie.

public static void ForEach<T>(this IEnumerable<T> @this, Action<T> action) 
{ 
    foreach (var x in @this) 
     action(x); 
} 
Powiązane problemy