Sintaxis de los métodos de extensión frente a la syntax de la consulta

Estoy tratando de entender si hay un buen momento para usar palabras clave linq estándar o métodos de extensión linq con expresiones lambda. Parece que hacen lo mismo, simplemente están escritos de manera diferente. ¿Es puramente una cuestión de estilo?

var query = from p in Products where p.Name.Contains("foo") orderby c.Name select p; // or with extension methods: var query = Products .Where(p => p.Name.Contains("foo")) .OrderBy(p => p.Name); 

Son muy similares, con el segundo ejemplo siendo un poco más escueto, pero quizás menos expresivo si no sabes lo que está haciendo el =>.

Además de escribir el código breve, ¿hay otras ventajas de usar los métodos de extensión en comparación con la syntax LINQ?

Honestamente, a veces puede ser situacional una vez que comienzas a usar Funcs y Actions. Digamos que estás usando estos tres funcs:

  Func userName = user => user.UserName; Func userIDOverTen = user => user.UserID < 10; Func userIDUnderTen = user => user.UserID > 10; 

Como puede ver, el primero reemplaza la expresión lamdba para obtener el nombre de usuario, el segundo reemplaza una expresión lamdba utilizada para verificar si el ID es menor que 10, y seamos sinceros, el tercero debería ser bastante fácil de entender ahora.

NOTA: Este es un ejemplo tonto pero funciona.

  var userList = from user in userList where userIDOverTen(user) select userName; 

Versus

  var otherList = userList .Where(IDIsBelowNumber) .Select(userName) 

En este ejemplo, el segundo es un poco menos detallado ya que el método de extensión puede hacer un uso completo del Func, pero la expresión Linq no puede, ya que se ve solo por un booleano en lugar de un Func que devuelve booleano. Sin embargo, aquí es donde podría ser mejor usar el lenguaje de expresión. Supongamos que ya tiene un método que abarca más que solo un usuario:

  private Boolean IDIsBelowNumber(DataClasses.User user, Int32 someNumber, Boolean doSomething) { return user.UserID < someNumber; } 

Nota: doSomething está allí simplemente porque el método de extensión where está bien con un método que toma un usuario y un entero y devuelve booleano. Algo molesto para este ejemplo.

Ahora, si miras la consulta de Linq:

  var completeList = from user in userList where IDIsBelowNumber(user, 10, true) select userName; 

Eres bueno para eso. Ahora el método de extensión:

  var otherList = userList .Where(IDIsBelowNumber????) .Select(userName) 

Sin una expresión lambda, realmente no puedo llamar a ese método. Entonces, ahora lo que tengo que hacer es crear un método que cree un Func basado en la llamada al método original.

  private Func IDIsBelowNumberFunc(Int32 number) { return user => IDIsBelowNumber(user, number, true); } 

Y luego enchúfalo:

  var otherList = userList .Where(IDIsBelowNumberFunc(10)) .Select(userName) 

Como puede ver, a veces puede ser más fácil usar el enfoque de consulta a veces.

Una ventaja del uso de los métodos de extensión LINQ ( consultas basadas en métodos) es que puede definir métodos de extensión personalizados y aún así leer bien.

Por otro lado, cuando se utiliza una expresión de consulta LINQ, el método de extensión personalizado no está en la lista de palabras clave. Se verá un poco extraño mezclado con las otras palabras clave.

Ejemplo

Estoy usando un método de extensión personalizado llamado Into cual solo toma una cadena:

Ejemplo con consulta

 var query = (from p in Products where p.Name.Contains("foo") orderby c.Name select p).Into("MyTable"); 

Ejemplo con métodos de extensión

 var query = Products .Where(p => p.Name.Contains("foo")) .OrderBy(p => p.Name) .Into("MyTable"); 

En mi opinión, este último, utilizando una consulta basada en el método , se lee mejor cuando tienes métodos de extensión personalizados.

Creo que es una buena idea no usarlos juntos y elegir uno y seguir con él.

Principalmente es un gusto personal, pero en la syntax de la consulta (método de comprensión) no todos los operadores están disponibles como se dijo anteriormente.

Encuentro la syntax de los Métodos de extensión más en línea con el rest de mi código. Hago mi SQL en SQL. También es muy fácil construir su expresión simplemente agregando todo encima uno del otro con los métodos de extensión.

Solo mis dos centavos.

Como aún no puedo hacer comentarios, quiero hacer uno aquí para la respuesta de la herramienta de progtwigción: ¿Por qué crear un método completamente nuevo para el último ejemplo? No puedes usar:

.Where(user => IDIsBelowNumber(user, 10, true))

Comstackn lo mismo, y son equivalentes. Personalmente, prefiero los métodos lambda (extensión) para la mayoría de las cosas, solo usando las declaraciones (estándar) si estoy haciendo LINQ to SQL o intentando simular SQL. Encuentro que los métodos lambda fluyen mejor con el código, mientras que los enunciados distraen visualmente.

Prefiero la syntax del método de extensión cuando uso métodos Linq que no tienen equivalente de syntax de consulta, como FirstOrDefault () u otros como ese.

Me gusta utilizar la syntax de consulta cuando realmente es una consulta, es decir, una expresión lenta que evalúa según demanda.

Un método que se parece a las llamadas a métodos regulares (syntax de método o syntax lambda) no se ve lo suficientemente flojo, así que lo uso como una convención. Por ejemplo,

 var query = from p in Products where p.Name.Contains("foo") orderby p.Name select p; var result = query.ToList(); //extension method syntax 

Si no es una consulta, me gusta el estilo fluido que me parece consistente con otras llamadas que ejecutan con entusiasmo.

 var nonQuery = Products.Where(p => p.Name.Contains("foo")) .OrderBy(p => p.Name) .ToList(); 

Me ayuda a diferenciar mejor los dos estilos de llamadas. Por supuesto, hay situaciones en las que se verá obligado a utilizar la syntax del método de todos modos, por lo que mi convención no es lo suficientemente convincente.

Una ventaja de los métodos de extensión / expresiones lynda es los operadores adicionales que se ofrecen como Skip y Take. Por ejemplo, si está creando un método de paginación, puede omitir los primeros 10 registros y tomar los siguientes 10 y es fácil de implementar.