2011-03-01 9 views
8

Yo prefiero usar métodos de extensión para las operaciones básicas de LINQ consulta: Where(), Select, pero para complejos Select(), SelectMany(), y especialmente OrderBy().ThenBy() declaraciones que encontrar la sintaxis de consulta que sea mucho más fácil de leer y natural.LINQ extensión de la mezcla y la sintaxis

Hoy me encontré con la siguiente consulta:

from c in _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => 
         c == anotherObject || c.Parent == anotherObject) 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 

es peligroso (para facilitar la lectura, capacidad de mantenimiento, o cualquier otro motivo) para mezclar consulta y extensión de la sintaxis?

Esto tiene el potencial de ser muy subjetivo, si lo es, lo siento si no cumple los requisitos para una buena pregunta subjetiva. ¡Avíseme si puedo mejorarlo!

Respuesta

6

¿Es peligroso (por legibilidad, mantenibilidad o por cualquier otro motivo) mezclar sintaxis de consulta y extensión?

El mayor peligro que vería es la adición potencial de "sorpresa" en su código, especialmente cuando es visto por otros desarrolladores.

Desde un punto de vista de compilación, la sintaxis de la consulta se traduce directamente en las llamadas al método de extensión, por lo que no hay necesariamente un problema técnico aquí. Sin embargo, esto potencialmente va a agregar llamadas a métodos adicionales que, a primera vista, no serían esperadas por muchos desarrolladores. Este podría conducir a un posible problema de mantenimiento.

Dicho esto, si se hace con moderación y con una buena razón, no creo que haya un problema real al mezclar la sintaxis. Esto es realmente bastante común; por ejemplo, si desea escribir en la sintaxis de la consulta, pero necesita evaluarlo completamente, a menudo está entre paréntesis con .ToList() agregado - o si desea usar PLINQ con sintaxis de consulta, a menudo es from x in collection.AsParallel() , que técnicamente está mezclando sintaxis también ...

+0

Gracias, esto respondió más directamente a la mayoría de mis pensamientos y preocupaciones. – Crisfole

3

Podría hacer algo como esto para hacer las cosas un poco más fáciles.

var firstQuery = _myObject.ObjectsParent.ParentsEnumerable 
       .Where(c => c == anotherObject || c.Parent == anotherObject); 

var secondQuery = from q in firstQuery.MyObjectsEnumerable 
        orderby firstQuery.SortKey, q.Description 
        select new { Item = q, 
           Text = firstQuery.Description + " -> " + q.Description }; 

Ahora sus consultas no se mezclan

+1

La primera línea es incorrecta ... usted debe caer el "de C en" ... –

+0

creo @ Reed Copsey-mea (* debe no) porque firstQuery no tiene la descripción de la propiedad solo un elemento de eso lo haría. Entonces este Código no funciona. – jbtule

1

utilizo los métodos de extensión, mi colega utiliza la sintaxis de la consulta. No hay diferencia.

Sin embargo, diría que debe dividir una consulta grande en otras más pequeñas para la depuración y la legibilidad ya que normalmente no hay costos de tiempo.

1

Habiendo hecho esto yo mismo (aunque no para .Where, pero para .Cast), diría que depende mucho de qué métodos de extensión esté llamando.

p. Ej. Me sentía perfectamente autorizado para utilizar .Cast porque no estaba disponible en el azúcar sintáctico (AFAIK), pero probablemente lo evitaría. Donde, porque eso tiene una representación en la sintaxis de la consulta.

Habiendo dicho eso, probablemente usaría .Seleccione para mutar datos en una consulta también ... Pero soy un poco sádico.

3

Esto es una especie de juicio, pero muchas preguntas de "mejores prácticas" tienden a ser, al menos al principio. Mi opinión es que deberías usar uno u otro en una sola declaración. No es realmente para cualquier "peligro" inherente a la mezcla, pero para mayor claridad.

En este caso particular, la cláusula where es muy simple, y la refactorizaría en la sintaxis de la consulta.

Sin embargo, hay casos que no se pueden expresar con elegancia en la sintaxis de la consulta. En los casos en que simplemente es inevitable mezclar sintaxis, las consultas (de nuevo IMO) serían más legibles si se divide la cadena de métodos en su propia variable, y luego simplemente hace referencia a esa variable en la declaración sintaxis de consulta. El uso de la suya como modelo:

//The method chain can be pulled out as its own variable... 
var filteredParents = _myObject.ObjectsParent.ParentsEnumerable 
        .Where(c => c == anotherObject || c.Parent == anotherObject); 

//...which you can then substitute in a now purely query-syntax statement 
from c in filteredParents 
from q in c.MyObjectsEnumerable 
orderby c.SortKey, q.Description 
select new { Item = q, Text = c.Description + " -> " + q.Description }; 
2

no creo que es peligroso mezclar, que creo que depende de lo que es más fácil de leer, la sintaxis de consulta es muy fácil de leer, pero no tan Flexable, por lo que la mezcla de algunos de encadenamiento parece una pequeño precio a pagar. Supongo que la respuesta es si crees que el siguiente encadenamiento completo es más legible que lo que escribiste, personalmente creo que el tuyo es más fácil de leer.

_myObject.ObjectsParent 
      .ParentsEnumerable 
      .Where(c => c == anotherObject || c.Parent == anotherObject) 
      .SelectMany(c => c.MyObjectsEnumerable, (c, q) => new {c, q}) 
      .OrderBy(t => t.c.SortKey) 
      .ThenBy(t => t.q.Description) 
      .Select(t => new {Item = t.q, Text = t.c.Description + " -> " + t.q.Description}); 
Cuestiones relacionadas