2009-03-20 12 views
66

Al escribir una consulta LINQ con varias condiciones "y", ¿debo escribir una sola cláusula where que contenga && o múltiples where cláusulas, una para cada condición?¿Debo usar dos cláusulas "where" o "&&" en mi consulta LINQ?

static void Main(string[] args) 
{ 
    var ints = new List<int>(Enumerable.Range(-10, 20)); 

    var positiveEvensA = from i in ints 
         where (i > 0) && ((i % 2) == 0) 
         select i; 

    var positiveEvensB = from i in ints 
         where i > 0 
         where (i % 2) == 0 
         select i; 

    System.Diagnostics.Debug.Assert(positiveEvensA.Count() == 
             positiveEvensB.Count()); 
} 

¿Hay alguna diferencia que no sea la preferencia personal o estilo de codificación (líneas largas, la legibilidad, etc.) entre positiveEvensA y positiveEvensB?

Una posible diferencia que viene a la mente es que los diferentes proveedores de LINQ pueden hacer frente mejor a múltiples where s en lugar de una expresión más compleja; ¿Es esto cierto?

Respuesta

45

Yo personalmente siempre iría con el & & frente a dos cláusulas donde cada vez que no hace que la declaración sea ininteligible.

En su caso, probablemente no se note en absoluto, pero tener 2 cláusulas where definitivamente tendrá un impacto en el rendimiento si tiene una colección grande, y si utiliza todos los resultados de esta consulta. Por ejemplo, si llama a .Count() en los resultados, o itera a través de toda la lista, se ejecutará la primera cláusula where, creando un nuevo IEnumerable que será completamente enumerado nuevamente, con un segundo delegado.

Encadenando las 2 cláusulas juntas hace que la consulta forme un único delegado que se ejecuta cuando se enumera la colección. Esto da como resultado una enumeración a través de la colección y una llamada al delegado cada vez que se devuelve un resultado.

Si las divides, las cosas cambian. Como su cláusula first where enumera a través de la colección original, la cláusula second where enumera sus resultados. Esto provoca, potencialmente (el peor de los casos), 2 enumeraciones completas a través de su colección y 2 delegados llamados por miembro, lo que podría significar que esta afirmación (teóricamente) podría tomar 2 veces la velocidad del tiempo de ejecución.

Si decides usar 2 cláusulas where, ubicar la cláusula más restrictiva primero ayudará bastante, ya que la segunda cláusula where solo se ejecuta en los elementos que pasan por la primera.

Ahora, en su caso, esto no importará. En una gran colección, podría. Como regla general, voy por:

1) La legibilidad y mantenibilidad

2) Rendimiento

En este caso, creo que ambas opciones son igualmente fácil de mantener, por lo que me gustaría ir para el opción más eficiente.

+29

Con 2 "dónde" cláusulas, que sigue siendo sólo una única iteración con 2 llamadas de delegados por artículo - no 2 iteraciones como se reivindica. –

+4

Marc, cuando digo dos iteraciones, debería haber sido más explícito. Con las cláusulas 2 where, construyes dos enumeradores separados: el primero crea un enumerador que se enumera por el segundo. Pero eso es bastante menor: no hace 2 bucles, solo enumera con enumeradores separados. –

+2

Creo que 'Where' tiene algunas optimizaciones especiales para el caso multiple cláusula where. Aún así será más lento debido a las múltiples invocaciones de delegados. – CodesInChaos

18

Esto es principalmente un problema de estilo personal. Personalmente, siempre que la cláusula where encaje en una línea, agrupo las cláusulas.

Usar múltiples where's tenderá a ser menos eficiente porque requiere una invocación de delegado adicional para cada elemento que lo hace tan lejos. Sin embargo, es probable que sea un problema insignificante y solo debe considerarse si un generador de perfiles lo muestra como un problema.

1

Como otros han sugerido, es más una preferencia personal. Me gusta el uso de & & ya que es más legible e imita la sintaxis de otros lenguajes principales.

Cuestiones relacionadas