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/

26voto

cdiggins Punkte 16400

Halten Sie Ihre Nebeneffekte aus meinem IEnumerable heraus

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

Wie andere bereits festgestellt haben aquí und im Ausland LINQ und IEnumerable Methoden sollen nebenwirkungsfrei sein.

Möchten Sie wirklich "etwas" mit jedem Element in der IEnumerable tun? Dann foreach ist die beste Wahl. Die Leute sind nicht überrascht, wenn hier Nebenwirkungen auftreten.

foreach (var i in items) i.DoStuff();

Ich wette, Sie wollen keinen Nebeneffekt

Meiner Erfahrung nach sind Nebenwirkungen jedoch in der Regel nicht erforderlich. Meistens gibt es eine einfache LINQ-Abfrage, die nur darauf wartet, entdeckt zu werden, begleitet von einer StackOverflow.com-Antwort von Jon Skeet, Eric Lippert oder Marc Gravell, die erklärt, wie man das tun kann, was man will!

Einige Beispiele

Wenn Sie tatsächlich nur einen Wert aggregieren (anhäufen), sollten Sie die Aggregate Erweiterungsmethode.

items.Aggregate(initial, (acc, x) => ComputeAccumulatedValue(acc, x));

Vielleicht möchten Sie eine neue IEnumerable aus den vorhandenen Werten.

items.Select(x => Transform(x));

Vielleicht möchten Sie auch eine Nachschlagetabelle erstellen:

items.ToLookup(x, x => GetTheKey(x))

Die Liste der Möglichkeiten (Wortspiel nicht ganz beabsichtigt) ist endlos.

10 Stimmen

Ah, Select ist also Map, und Aggregate ist Reduce.

25voto

Dor Rotman Punkte 1433

Ich habe Fredriks Methode übernommen und den Rückgabetyp geändert.

Auf diese Weise unterstützt die Methode verzögerte Ausführung wie andere LINQ-Methoden.

EDIT : Falls dies nicht klar war: Jede Verwendung dieser Methode muss mit ToList() enden oder eine andere Möglichkeit, die Methode zu zwingen, auf die gesamte Aufzählungsliste zu wirken. Andernfalls würde die Aktion nicht ausgeführt werden!

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

Und hier ist der Test, um das zu sehen:

[Test]
public void TestDefferedExecutionOfIEnumerableForEach()
{
    IEnumerable<char> enumerable = new[] {'a', 'b', 'c'};

    var sb = new StringBuilder();

    enumerable
        .ForEach(c => sb.Append("1"))
        .ForEach(c => sb.Append("2"))
        .ToList();

    Assert.That(sb.ToString(), Is.EqualTo("121212"));
}

Wenn Sie die ToList() am Ende wird der Test fehlschlagen, da der StringBuilder eine leere Zeichenfolge enthält. Das liegt daran, dass keine Methode ForEach zum Aufzählen gezwungen hat.

0 Stimmen

Ihre alternative Implementierung von ForEach ist interessant, entspricht aber nicht dem Verhalten von List.ForEach dessen Unterschrift lautet public void ForEach(Action<T> action) . Es entspricht auch nicht dem Verhalten der Observable.ForEach Erweiterung auf IObservable<T> dessen Unterschrift lautet public static void ForEach<TSource>(this IObservable<TSource> source, Action<TSource> onNext) . Übrigens, die ForEach Äquivalent auf Scala-Sammlungen, auch diejenigen, die faul sind, haben auch Rückgabetyp, die void in C # entspricht.

1 Stimmen

Dies ist die beste Antwort: aufgeschobene Ausführung + fließende API.

4 Stimmen

Dies funktioniert genau so wie der Aufruf von Select avec ToList . Der Zweck der ForEach ist es, nicht anrufen zu müssen ToList . Sie sollte sofort ausgeführt werden.

18voto

regisbsb Punkte 3555

Wenn Sie als Aufzählungsrollen fungieren wollen, sollten Sie Ertrag jeden Artikel.

public static class EnumerableExtensions
{
    public static IEnumerable<T> ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
    {
        foreach (var item in enumeration)
        {
            action(item);
            yield return item;
        }
    }
}

0 Stimmen

Dies ist nicht wirklich ein ForEach, wenn Sie das Element zurückgeben, es ist eher wie ein Tap.

11voto

John Wigger Punkte 904

Es gibt eine experimentelle Veröffentlichung von Microsoft von Interaktive Erweiterungen von LINQ (auch über NuGet siehe Das Profil von RxTeams für weitere Links). Die Kanal 9 Video erklärt es gut.

Die Dokumente werden nur im XML-Format bereitgestellt. Ich habe dies ausgeführt Dokumentation in der Sandburg um sie in ein lesbareres Format zu bringen. Entpacken Sie das Docs-Archiv und suchen Sie nach index.html .

Neben vielen anderen Vorteilen bietet es die erwartete ForEach-Implementierung. Sie ermöglicht es Ihnen, Code wie diesen zu schreiben:

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8 };

numbers.ForEach(x => Console.WriteLine(x*x));

2 Stimmen

Der funktionierende Link zu den interaktiven Erweiterungen: microsoft.com/download/de/details.aspx?id=27203

8voto

Wolf5 Punkte 15450

Laut PLINQ (verfügbar seit .Net 4.0) können Sie eine

IEnumerable<T>.AsParallel().ForAll() 

um eine parallele foreach-Schleife für eine IEnumerable auszuführen.

0 Stimmen

Solange ihre aktion thread-sicher ist, ist alles gut. aber was passiert, wenn sie eine nicht-thread-sichere aktion durchführen müssen? das kann ein ziemliches chaos verursachen...

2 Stimmen

Das stimmt. Es ist nicht thread-sicher, es werden verschiedene Threads aus einem Thread-Pool verwendet... Und ich muss meine Antwort revidieren. Wenn ich es jetzt versuche, gibt es kein ForEach(). Muss mein Code gewesen sein, der eine Erweiterung mit ForEach enthält, als ich darüber nachdachte.

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