Pergunta

Em LINQ, métodos de extensão como Where devolver um IEnumerable coleção, mas métodos de classificação como OrderBy devolver um IOrderedEnumerable coleção.

Então, se você tem uma consulta que termina com OrderBy (ou seja, retorna um IOrderedEnumerable), você não pode mais tarde anexar um Where Método - o compilador reclama do tipo que está sendo transmitido Where.

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id);

query = query.Where(p => p.ProcessName.Length < 5);

No entanto, se você fizer tudo isso em uma consulta, tudo bem!

var query = Process.GetProcesses()
            .Where(p => p.ProcessName.Length < 10)
            .OrderBy(p => p.Id)
            .Where(p => p.ProcessName.Length < 5);

Eu olhei para a Assembléia no Reflector para ver se o compilador estava reordenando alguma das operações, mas não parece ter. Como é que isso funciona?

Foi útil?

Solução

IOrderedEnumerable<T> estende -se IEnumerable<T> Portanto, você ainda pode usar qualquer um dos métodos de extensão. O motivo pelo qual seu primeiro bloco de código não funcionou é porque você escreveu efetivamente:

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);

Isso falha porque query.Where(...) Retorna apenas um IEnumerable<Process>, que não pode ser atribuído ao query variável. Não está ligando Where Esse é o problema - ele está atribuindo o resultado de volta à variável original. Para demonstrar isso, esse código funcionará bem:

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);

Como alternativa, você pode declarar a consulta como IEnumerable<T> começar com:

IEnumerable<Process> query = Process.GetProcesses()
                                    .Where(p => p.ProcessName.Length < 10)
                                    .OrderBy(p => p.Id);

// Fine
query = query.Where(p => p.ProcessName.Length < 5);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top