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?

Était-ce utile?

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);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top