877 Stimmen

LINQ-Entsprechung von foreach für IEnumerable<T>

Ich möchte das Äquivalent der folgenden in LINQ zu tun, aber ich kann nicht herausfinden, wie:

IEnumerable<Item> items = GetItems();
items.ForEach(i => i.DoStuff());

Was ist die richtige Syntax?

4 Stimmen

@pst: Ich habe diese Erweiterungsmethoden immer blindlings in meine Projekte gesteckt. Danke für diesen Artikel.

3 Stimmen

Es gibt MehrLINQ die eine ForEach Erweiterung .

0 Stimmen

Hier ist eine alternative Idee, wie dies könnte möglich sein: visualstudio.uservoice.com/forums/121579-visual-studio-2015/

7voto

Tormod Punkte 4245

Der Zweck von ForEach ist es, Nebeneffekte zu verursachen. IEnumerable ist für die faule Aufzählung einer Menge gedacht.

Dieser konzeptionelle Unterschied wird deutlich, wenn man ihn betrachtet.

SomeEnumerable.ForEach(item=>DataStore.Synchronize(item));

Dies wird nicht ausgeführt, bis Sie eine "count" oder eine "ToList()" oder etwas auf sie tun. Es ist eindeutig nicht das, was ausgedrückt wird.

Sie sollten die IEnumerable-Erweiterungen verwenden, um Iterationsketten einzurichten und den Inhalt durch ihre jeweiligen Quellen und Bedingungen zu definieren. Expression Trees sind mächtig und effizient, aber Sie sollten lernen, ihre Natur zu schätzen. Und zwar nicht nur für die Programmierung um sie herum, um ein paar Zeichen zu sparen, indem man die faule Auswertung außer Kraft setzt.

5voto

Nenad Punkte 22188

Viele Leute haben es erwähnt, aber ich musste es aufschreiben. Ist das nicht am klarsten/lesbarsten?

IEnumerable<Item> items = GetItems();
foreach (var item in items) item.DoStuff();

Kurz und einfach(er).

0 Stimmen

Sie können die gesamte erste Zeile weglassen und GetItems direkt in foreach verwenden

3 Stimmen

Ja, natürlich. Aus Gründen der Klarheit ist es so geschrieben. Damit es klar ist, was GetItems() Methode zurück.

4 Stimmen

Wenn ich jetzt meinen Kommentar lese, sehe ich, dass es so aussieht, als würde ich Ihnen etwas sagen, was Sie nicht wissen. So habe ich das nicht gemeint. Was ich meinte, ist, dass foreach (var item in GetItems()) item.DoStuff(); ist einfach eine Schönheit.

4voto

Paulustrious Punkte 595

Jetzt haben wir die Möglichkeit,...

        ParallelOptions parallelOptions = new ParallelOptions();
        parallelOptions.MaxDegreeOfParallelism = 4;
#if DEBUG
        parallelOptions.MaxDegreeOfParallelism = 1;
#endif
        Parallel.ForEach(bookIdList, parallelOptions, bookID => UpdateStockCount(bookID));

Das eröffnet natürlich ein ganz neues Feld für Fadenwürmer.

ps (Entschuldigung für die Schriftarten, das System hat das so entschieden)

4voto

Mark Seemann Punkte 216836

Wie in zahlreichen Antworten bereits erwähnt wurde, können Sie eine solche Erweiterungsmethode leicht selbst hinzufügen. Wenn Sie das jedoch nicht tun wollen, obwohl mir nichts dergleichen in der BCL bekannt ist, gibt es immer noch eine Option in der System Namespace, wenn Sie bereits einen Verweis auf Reaktive Erweiterung (und wenn nicht, sollten Sie es tun):

using System.Reactive.Linq;

items.ToObservable().Subscribe(i => i.DoStuff());

Obwohl die Methodennamen etwas anders lauten, ist das Endergebnis genau das, wonach Sie suchen.

0 Stimmen

Sieht so aus, als ob dieses Paket jetzt veraltet ist

4voto

Rm558 Punkte 3759

ForEach kann auch sein Verkettete nach der Aktion einfach wieder auf die Stapellinie gelegt. fließend bleiben


Employees.ForEach(e=>e.Act_A)
         .ForEach(e=>e.Act_B)
         .ForEach(e=>e.Act_C);

Orders  //just for demo
    .ForEach(o=> o.EmailBuyer() )
    .ForEach(o=> o.ProcessBilling() )
    .ForEach(o=> o.ProcessShipping());

//conditional
Employees
    .ForEach(e=> {  if(e.Salary<1000) e.Raise(0.10);})
    .ForEach(e=> {  if(e.Age   >70  ) e.Retire();});

Eine Eifrig Version der Implementierung.

public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (T item in enu) action(item);
    return enu; // make action Chainable/Fluent
}

Editar: a Faule Version ist die Verwendung der Rendite, wie este .

public static IEnumerable<T> ForEachLazy<T>(this IEnumerable<T> enu, Action<T> action)
{
    foreach (var item in enu)
    {
        action(item);
        yield return item;
    }
}

Die faule Version NEEDs materialisiert werden, z. B. ToList(), sonst passiert nichts. siehe unten tolle Kommentare von ToolmakerSteve.

IQueryable<Product> query = Products.Where(...);
query.ForEachLazy(t => t.Price = t.Price + 1.00)
    .ToList(); //without this line, below SubmitChanges() does nothing.
SubmitChanges();

Ich habe sowohl ForEach() als auch ForEachLazy() in meiner Bibliothek.

2 Stimmen

Haben Sie dies getestet? Es gibt mehrere Zusammenhänge, in denen sich diese Methode kontraintuitiv verhält. Besser wäre es foreach(T item in enu) {action(item); yield return item;}

3 Stimmen

Dies führt zu mehreren Aufzählungen

0 Stimmen

Interessant. Ich denke darüber nach, wann ich das oben genannte für eine Folge von 3 Aktionen tun möchte, anstatt foreach (T item in enu) { action1(item); action2(item); action3(item); } ? Eine einzige, explizite Schleife. Ich denke, wenn es wichtig wäre, etwas zu tun todo die action1's BEVOR sie mit action2's beginnen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X