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/

3voto

Scott Nimrod Punkte 10821

Angeregt durch Jon Skeet habe ich seine Lösung um die folgende erweitert:

Erweiterungsmethode:

public static void Execute<TSource, TKey>(this IEnumerable<TSource> source, Action<TKey> applyBehavior, Func<TSource, TKey> keySelector)
{
    foreach (var item in source)
    {
        var target = keySelector(item);
        applyBehavior(target);
    }
}

Kunde:

var jobs = new List<Job>() 
    { 
        new Job { Id = "XAML Developer" }, 
        new Job { Id = "Assassin" }, 
        new Job { Id = "Narco Trafficker" }
    };

jobs.Execute(ApplyFilter, j => j.Id);

. . .

    public void ApplyFilter(string filterId)
    {
        Debug.WriteLine(filterId);
    }

2voto

Zar Shardan Punkte 5257

Diese Abstraktion des "funktionalen Ansatzes" hat große Lücken. Nichts auf der Sprachebene verhindert Seiteneffekte. Solange Sie es schaffen, Ihr Lambda/Delegat für jedes Element im Container aufzurufen, erhalten Sie das "ForEach"-Verhalten.

Hier zum Beispiel eine Möglichkeit, srcDictionary in destDictionary zusammenzuführen (wenn der Schlüssel bereits existiert - überschreibt)

Dies ist ein Hack und sollte in keinem Produktionscode verwendet werden.

var b = srcDictionary.Select(
                             x=>
                                {
                                  destDictionary[x.Key] = x.Value;
                                  return true;
                                }
                             ).Count();

8 Stimmen

Wenn Sie diesen Haftungsausschluss hinzufügen müssen, sollten Sie ihn wahrscheinlich nicht veröffentlichen. Nur meine Meinung.

2 Stimmen

Wie zum Teufel soll das besser sein als foreach(var tuple in srcDictionary) { destDictionary[tuple.Key] = tuple.Value; } ? Wenn nicht im Produktionscode, wo und warum sollten Sie dies überhaupt verwenden?

3 Stimmen

Dies nur, um zu zeigen, dass es prinzipiell möglich ist. Es geschieht auch zu tun, was OP fragte nach, und ich deutlich darauf hingewiesen, es sollte nicht in der Produktion verwendet werden, noch neugierig und hat pädagogischen Wert.

2voto

solublefish Punkte 1441

MoreLinq hat IEnumerable<T>.ForEach und eine Menge anderer nützlicher Erweiterungen. Es lohnt sich wahrscheinlich nicht, die Abhängigkeit nur für ForEach aber es gibt eine Menge nützlicher Dinge darin.

https://www.nuget.org/packages/morelinq/

https://github.com/morelinq/MoreLINQ

1voto

Ich bin nicht einverstanden mit der Vorstellung, dass Link-Erweiterungsmethoden frei von Seiteneffekten sein sollten (nicht nur, weil sie es nicht sind, jeder Delegat kann Seiteneffekte ausführen).

Bedenken Sie Folgendes:

   public class Element {}

   public Enum ProcessType
   {
      This = 0, That = 1, SomethingElse = 2
   }

   public class Class1
   {
      private Dictionary<ProcessType, Action<Element>> actions = 
         new Dictionary<ProcessType,Action<Element>>();

      public Class1()
      {
         actions.Add( ProcessType.This, DoThis );
         actions.Add( ProcessType.That, DoThat );
         actions.Add( ProcessType.SomethingElse, DoSomethingElse );
      }

      // Element actions:

      // This example defines 3 distict actions
      // that can be applied to individual elements,
      // But for the sake of the argument, make
      // no assumption about how many distict
      // actions there may, and that there could
      // possibly be many more.

      public void DoThis( Element element )
      {
         // Do something to element
      }

      public void DoThat( Element element )
      {
         // Do something to element
      }

      public void DoSomethingElse( Element element )
      {
         // Do something to element
      }

      public void Apply( ProcessType processType, IEnumerable<Element> elements )
      {
         Action<Element> action = null;
         if( ! actions.TryGetValue( processType, out action ) )
            throw new ArgumentException("processType");
         foreach( element in elements ) 
            action(element);
      }
   }

Was das Beispiel zeigt, ist eigentlich nur eine Art der späten Bindung, die es erlaubt, eine von vielen möglichen Aktionen mit Seiteneffekten auf eine Folge von Elementen aufzurufen, ohne ein großes Switch-Konstrukt schreiben zu müssen, um den Wert zu dekodieren, der die Aktion definiert, und ihn in die entsprechende Methode zu übersetzen.

9 Stimmen

Es gibt einen Unterschied zwischen der Frage, ob eine Erweiterungsmethode Nebenwirkungen haben KANN, und der Frage, ob sie welche haben SOLLTE. Sie weisen nur darauf hin, dass sie Nebenwirkungen haben kann, während es sehr gute Gründe dafür geben kann, dass sie keine Nebenwirkungen haben sollte. In der funktionalen Programmierung sind alle Funktionen frei von Seiteneffekten, und wenn Sie Konstrukte der funktionalen Programmierung verwenden, sollten Sie davon ausgehen, dass sie es sind.

1voto

Alex Punkte 3047

Um flüssig zu bleiben, kann man einen solchen Trick anwenden:

GetItems()
    .Select(i => new Action(i.DoStuf)))
    .Aggregate((a, b) => a + b)
    .Invoke();

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