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?

War es hilfreich?

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);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top