2009-05-13 12 views
47

Mögliche Duplizieren mit:
Why is there not a ForEach extension method on the IEnumerable interface?Lambda Expression Foreach Klausel

EDIT

als Referenz, hier ist der Blog-Post, die eric in den Kommentaren referrrred zu

http://blogs.msdn.com/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx

ORIG

Mehr von Kuriosität Ich nehme an, sondern ein für die C# Spezifikation Savants ...

Warum ist es, dass die foreach() Klausel funktioniert nicht (oder nicht verfügbar) für den Einsatz auf IQueryable/IEnumerable Ergebnismengen ...

Sie müssen zuerst Ihre Ergebnisse ToList() oder ToArray() konvertieren theres Vermutlich eine technische Beschränkung auf die Art und Weise C# Iterierten IEnumerables Vs. Listen ... Hat etwas mit der verzögerten Ausführung von IEnumerables/IQuerable Collections zu tun. z.B.

var userAgentStrings = uasdc.UserAgentStrings 
    .Where<UserAgentString>(p => p.DeviceID == 0 && 
          !p.UserAgentString1.Contains("msie")); 
//WORKS    
userAgentStrings.ToList().ForEach(uas => ProcessUserAgentString(uas));   

//WORKS 
Array.ForEach(userAgentStrings.ToArray(), uas => ProcessUserAgentString(uas)); 

//Doesn't WORK 
userAgentStrings.ForEach(uas => ProcessUserAgentString(uas)); 
+4

Ich würde 'ForEach (uac => ProcessUserAgentString (uas))' als 'ForEach (ProcessUserAgentString)' schreiben. –

+1

Was ist das Problem mit einer herkömmlichen For-Each-Schleife? foreach (in UserAgentStrings var uas) ProcessUserAgentString (uas); – Dario

+0

Theres kein Problem ...Wie gesagt, es war eher eine Kuriosität, warum die Konvention für Arrays/Listen verfügbar war, aber nicht für IQueryables/IEnumerables. Eric Lippert wies darauf hin, dass dies eine vollkommen philosophische Entscheidung des Entwicklerteams ist und nicht aus technischen Gründen –

Antwort

55

Was für ein erstaunlichen Zufall, schrieb ich gerade jetzt ein Blogartikel über diese Frage. Es wird was published May 18th sein. Es gibt keinen technischen Grund, warum wir (oder Sie!) Das nicht tun könnten. Die Gründe, warum nicht, sind philosophisch. Sehen Sie meinen Blog nächste Woche für mein Argument.

+1

Ich verstehe nicht, warum Sie es nicht für nützlich halten, wenn Sie eine Reihe von Methoden miteinander verketten, wie .Wo (...). Wählen Sie (...). ForEach (...); – Micah

+5

@Micah: Welcher Grund, den ich in meinem Artikel gab, war unklar? Ich glaube, es ist nützlich. Ich glaube, dass es * nicht ausreichend nützlich * ist, um die Arbeit zu rechtfertigen, und dass es schlechte Programmierpraktiken wie das Einbetten von Nebenwirkungen in logisch aussehende Abfragen fördert. Jeder Grund reicht aus, um diese Methode nicht hinzuzufügen. –

+0

@EricLippert Warum wurde es doch hinzugefügt? –

13

Es ist durchaus möglich, eine ForEach Erweiterungsmethode für IEnumerable<T> zu schreiben.

Ich bin nicht wirklich sicher, warum es nicht als Einbau-Erweiterungsmethode enthalten ist:

  • Vielleicht, weil ForEach bereits auf List<T> existierte und Array vor LINQ.
  • Vielleicht, weil es einfach ist, eine foreach Schleife zu verwenden, um die Sequenz zu iterieren.
  • Vielleicht weil es nicht funktional genug war/LINQy genug.
  • Vielleicht weil es nicht verkettbar ist. (Es ist leicht genug, um eine verkettbar Version dass yield s jedes Element zu machen, nachdem eine Aktion auszuführen, aber das Verhalten ist nicht besonders intuitiv.)

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); 
    } 
} 
+0

Punkt genommen, aber die Frage war mehr in Bezug auf warum es nicht out of the box verfügbar ist ... dh Array hat eine statische 'ForEach()' Methode. Liste hat einen ... Warum nicht IEnumerable/IQueryable –

+0

Ich denke, wir müssen auf Erics Blog-Post warten, um die echte Antwort zu finden;) – LukeH

+0

Ihre Vermutungen sind bemerkenswert ähnlich zu meinem Posting. –

Verwandte Themen