Comment utiliser LINQ méthodes IEnumerable après une méthode IOrderedEnumerable?
-
21-09-2019 - |
Question
Dans LINQ, les méthodes d'extension comme Where
renvoient une collection IEnumerable
, mais les méthodes de tri comme OrderBy
renvoient une collection IOrderedEnumerable
.
Donc, si vous avez une question qui se termine par OrderBy
(à savoir retourne un IOrderedEnumerable
), vous ne pouvez pas ajouter plus tard, une méthode Where
- le compilateur se plaint du type étant passé dans Where
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
query = query.Where(p => p.ProcessName.Length < 5);
Cependant, si vous le faites en une seule requête, il est très bien!
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id)
.Where(p => p.ProcessName.Length < 5);
Je l'ai regardé l'ensemble réflecteur pour voir si le compilateur a été ré-ordonner l'une des opérations, mais il ne semble pas avoir. Comment ça marche?
La solution
IOrderedEnumerable<T>
étend IEnumerable<T>
de sorte que vous pouvez toujours utiliser l'une des méthodes d'extension. La raison pour laquelle votre premier bloc de code ne fonctionne pas parce que vous avez effectivement écrit:
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);
Cela échoue parce que query.Where(...)
retourne seulement une IEnumerable<Process>
, qui ne peut être attribué à la variable query
. Il est de ne pas appeler Where
qui est le problème - il est l'affectation du résultat à la variable d'origine. Pour démontrer que, ce code fonctionne très bien:
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);
Vous pouvez déclarer la requête à IEnumerable<T>
commencer par:
IEnumerable<Process> query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Fine
query = query.Where(p => p.ProcessName.Length < 5);