Sagen wir haben list.Where(p=>p.Number > n).Select(p=> p.Name).Where(n=> n.StartsWith(a)).ToList();
wird dies ein Durchlaufalgorithmus oder es wird 3 Pässe sein?Versucht LINQ, Dinge in einem Durchgang zu lösen?
Antwort
Es wird die Liste in einem Durchgang aufbauen, aufgrund der Art, wie LINQ die Daten streamt.
Nehmen wir zum Beispiel diese:
var query = list.Where(p => p.Number > n);
Das ist an sich nicht sieht jede der Elemente der Liste. Stattdessen merkt es sich die Liste, die Sie betrachten, und wenn Sie über query
iterieren, werden bei jeder Abfrage nach dem nächsten Element die Elemente der Liste nacheinander überprüft, bis eine Übereinstimmung gefunden wird. Zum Beispiel:
using (var iterator = query.GetEnumerator())
{
iterator.MoveNext(); // This will look for the first match
Console.WriteLine(iterator.Current);
iterator.MoveNext(); // This will continue from just after the first match
}
Jede der Operationen funktioniert so - so durch die Zeit, die Sie haben:
var query = list.Where(...)
.Select(...)
.Where(...);
..., wenn Sie für den ersten Punkt fragen innerhalb query
, wird es Kette Backup (also die letzte Where
wird das Ergebnis von Select
fragen, die das Ergebnis der ersten Where
fragen wird, die die Liste fragen wird) und weitermachen, bis es ein Ergebnis hat. Dann, wenn Sie für das nächste Element fragen, dass das Ergebnis der Select
für das nächste Element fragen usw.
ToList
up baut ein List<T>
von allen Elementen in der Quelle, sofort - es ist eifrig in diesem Sinne (eher als die anderen Betreiber hier, die sind faul). Die ursprüngliche Liste selbst wird jedoch nur einmal durchlaufen.
Für eine viel weitere Einzelheiten über LINQ to Objects funktioniert - einschließlich einer Beispielimplementierung - Sie könnten meine Edulinq blog series lesen möchten.
list
würde nur einmal in diesem Code, nicht 3 Mal iteriert werden.
Natürlich, wenn Sie, wenn eine beliebige Abfrage testen wollen die Quelle mehrmals iteriert es einfach genug ist experimentell zu testen, nur ein IEnumerable
erstellen, die eine Ausnahme auslöst, wenn Sie versuchen, es mehrmals zu wiederholen:
public static IEnumerable<T> ThereCanBeOnlyOne<T>(this IEnumerable<T> source)
{
return new SingleEnumerable<T>(source);
}
private class SingleEnumerable<T> : IEnumerable<T>
{
private bool hasRun = false;
private IEnumerable<T> wrapped;
public SingleEnumerable(IEnumerable<T> wrapped)
{
this.wrapped = wrapped;
}
public IEnumerator<T> GetEnumerator()
{
if (hasRun)
throw new InvalidOperationException(
"Sequence cannot be enumerated multilpe times");
else
{
hasRun = true;
return wrapped.GetEnumerator();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Jetzt können Sie einfach schreiben:
list.ThereCanBeOnlyOne()
.Where(p=>p.Number > n)
.Select(p=> p.Name)
.Where(n=> n.StartsWith(a))
.ToList();
Wenn der Code eine Ausnahme auslöst, können Sie die zugrunde liegende Liste mehrere Male zu wiederholen versucht. Wenn nicht, hast du es nicht getan.
- 1. Assembly versucht, falsche Assembly-Version zu lösen
- 2. Machen Sie das in einem einzigen Durchgang?
- 3. MyISAM Schlüssellängenbeschränkung, versucht, Dinge mit MD5 der Felder zu beschleunigen
- 4. Docker Ignoriert limits.conf (versucht "zu viele offene Dateien" zu lösen)
- 5. Mehrere Java-Ersetzungen bei einem einzigen Durchgang
- 6. remote_directory Ressource in einem Anbieter versucht, Pfad in Wrapper Kochbuch zu lösen
- 7. Linq Dynamische ParseLambda nicht lösen
- 8. Dinge zu beachten beim Wechsel von LINQ nach SQL -> LINQ zu Entities
- 9. Welches Problem versucht Microsoft mit all diesen Datenzugriffsstrategien zu lösen?
- 10. versucht, ein C++ Beispiel zu lösen und leere Ausgabe
- 11. Führen Sie mehrere Reduzierungen in einem einzigen Durchgang in Clojure
- 12. Spark - Mehrere Filter auf RDD in einem Durchgang
- 13. Eine einzeilige Alternative für xp_cmdshell? Ich habe versucht, einige Dinge
- 14. Versucht, Werte in einem Feld mit einem Cursor zu ändern
- 15. Versucht, Linq-Abfragen zu verketten, aber nicht erfolgreich
- 16. Versucht, eine linke Verknüpfung zu einer LINQ-Anweisung hinzuzufügen
- 17. Scala Sammlungen: Inhalt und Art der Sammlung in einem Durchgang zu transformieren
- 18. C++ mehrere Strings in einem String in einem einzigen Durchgang ersetzen
- 19. LINQ - Helfen Sie mir, es mit einem Beispiel zu verstehen. Ich denke, LINQ sollte es lösen können!
- 20. Versucht OpenGL ES 1.1 Dinge zu rendern, die nicht auf dem Bildschirm angezeigt werden?
- 21. Was sind die wichtigsten Dinge auf einem Entwicklungsserver zu haben?
- 22. Versucht, etwas in Text mit einem Regex zu wählen
- 23. Versucht, eine Verknüpfung zu einem Verzeichnis zu erstellen
- 24. 'Versucht, zu einem View-Controller zu gelangen, der nicht existiert.'
- 25. Erforderlich zu lösen und mit HTTPServletRequest zu lösen
- 26. Doppelter Zeiger gegen Durchgang durch Referenzzeiger
- 27. versucht PHP ein Array in einem Array
- 28. Nicht in der Lage, Konflikte zu sehen und zu lösen
- 29. versucht, POST zu verwenden, aber API versucht, GET zu verwenden
- 30. Pass LINQ Ausdruck zu einem anderen Queryprovider
Angenommen, wir haben eine Staatsprüfung, und die Schüler werden gebeten, eine einfache algorithmische Aufgabe zu lösen, die über C# LINQ in einer netten, einfachen Abfrage gelöst werden kann. Wenn sie jedoch in einem Durchgang nicht in Läufen beweisen können, wird dies als eine nicht optimale Lösung angesehen und die Schüler bekommen schlechte Noten. – Rella
Beachten Sie, dass es eine ähnliche Frage zu Linq2SQL gibt: Wird die resultierende Abfrage mit einer einzelnen 'SELECT' Anweisung ausgeführt? Für einfache Abfragen wie Ihr Beispiel, wenn sie in eine SQL-Abfrage konvertiert werden können, ist die Antwort ja. Aber einige [komplex] (http://stackoverflow.com/q/22816591/256431) [Anfragen] (http://Stackoverflow.com/q/12264751/256431) tun dies nicht, und ich weiß nicht, ob jede Garantie ist gegeben. –