Wie verwendet Linq IEnumerable Methoden nach einer IOrderedEnumerable Methode?
-
21-09-2019 - |
Frage
In Linq, Erweiterungsmethoden wie Where
eine IEnumerable
Sammlung zurück, aber Sortiermethoden wie OrderBy
eine IOrderedEnumerable
Sammlung zurück.
Also, wenn Sie eine Abfrage, die Enden mit OrderBy
(d gibt eine IOrderedEnumerable
), können Sie später nicht mehr append ein Where
Methode -. Der Compiler beschwert sich über die Art in Where
weitergegeben werden
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
query = query.Where(p => p.ProcessName.Length < 5);
Allerdings, wenn Sie es tun, alle in einer Abfrage, es ist in Ordnung!
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id)
.Where(p => p.ProcessName.Length < 5);
Ich habe bei der Montage in Reflector sehe nach, ob der Compiler wurde jede der Operationen Nachbestellung, aber es scheint nicht zu haben. Wie funktionierts?
Lösung
IOrderedEnumerable<T>
erstreckt IEnumerable<T>
, so dass Sie immer noch eine der Erweiterungsmethoden verwenden können. Der Grund, Ihr erster Codeblock hat nicht funktioniert, weil Sie effektiv geschrieben:
IOrderedEnumerable<Process> query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Fail: can't assign an IEnumerable<Process> into a variable
// of type IOrderedEnumerable<Process>
query = query.Where(p => p.ProcessName.Length < 5);
Das schlägt fehl, weil query.Where(...)
nur eine IEnumerable<Process>
zurückgibt, die nicht mit dem query
Variablen zugewiesen werden kann. Es ist nicht Where
ruft das ist das Problem - es das Ergebnis wieder auf die ursprüngliche Variable zuweisen. Um zu zeigen, dass, wird dieser Code gut funktionieren:
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Introduce a new variable instead of trying to reuse the previous one
var query2 = query.Where(p => p.ProcessName.Length < 5);
Alternativ können Sie erklären Abfrage IEnumerable<T>
zu sein beginnen mit:
IEnumerable<Process> query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Fine
query = query.Where(p => p.ProcessName.Length < 5);