Pregunta

En Linq, métodos de extensión como Where volver una colección IEnumerable, pero los métodos de clasificación como OrderBy volver una colección IOrderedEnumerable.

Por lo tanto, si usted tiene una consulta que termina con OrderBy (es decir, devuelve un IOrderedEnumerable), no se puede añadir más tarde un método Where - el compilador se queja sobre el tipo que se pasa en Where

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

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

Sin embargo, si lo hace todo en una sola consulta, está bien!

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

He mirado en el conjunto de reflector para ver si el compilador fue re-ordenar cualquiera de las operaciones, pero no parecen tener. ¿Cómo funciona esto?

¿Fue útil?

Solución

IOrderedEnumerable<T> extiende IEnumerable<T> lo que aún puede utilizar cualquiera de los métodos de extensión. La razón de su primer bloque de código no funcionaba se debe a que había escrito con eficacia:

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

que falle debido query.Where(...) sólo devuelve un IEnumerable<Process>, que no puede ser asignado a la variable query. No está llamando Where ese es el problema - es asignar el resultado a la variable original. Para demostrar que, este código funciona muy 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);

Como alternativa, se puede declarar consulta que se IEnumerable<T> a comenzar con:

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 bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top