Pregunta

Estoy tratando de controlar si hay un buen momento para usar palabras clave linq estándar o métodos de extensión linq con expresiones lambda. Parecen hacer lo mismo, solo están escritos de manera diferente. ¿Es pura 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 y el segundo ejemplo es un poco más conciso, pero tal vez menos expresivo si no sabes lo que es = > está haciendo.

Además de escribir código conciso, ¿existen otras ventajas al usar los métodos de extensión en lugar de la sintaxis LINQ?

¿Fue útil?

Solución

Honestamente, a veces puede ser situacional una vez que comienzas a usar Funciones y Acciones. Digamos que está utilizando estos tres funcs:

  Func<DataClasses.User, String> userName = user => user.UserName;
  Func<DataClasses.User, Boolean> userIDOverTen = user => user.UserID < 10;
  Func<DataClasses.User, Boolean> 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 inferior a 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 de Func, pero la expresión de Linq no puede, ya que busca solo un Boolean en lugar de un Func que devuelve boolean. Sin embargo, aquí es donde podría ser mejor usar el lenguaje de expresión. Digamos que ya tenía 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á justo allí porque el método de extensión where está bien con un método que toma un usuario y un entero y devuelve boolean. Un poco molesto para este ejemplo.

Ahora, si observa 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<DataClasses.User, Boolean> IDIsBelowNumberFunc(Int32 number)
   {
      return user => IDIsBelowNumber(user, number, true);
   }

Y luego conéctelo:

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

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

Otros consejos

Una ventaja de usar 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 que 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, usando 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 sintaxis de consulta (método de comprensión) no todos los operadores están disponibles como se dijo anteriormente.

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

Solo mis dos centavos.

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

.Where (user = > IDIsBelowNumber (usuario, 10, verdadero))

Compilan 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 de otra manera intento emular SQL. Me parece que los métodos lambda fluyen mejor con el código, mientras que las declaraciones distraen visualmente.

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

Me gusta usar la sintaxis de consulta cuando realmente es una consulta, es decir, una expresión perezosa que se evalúa bajo demanda.

Un método que se parece a las llamadas a métodos normales (sintaxis de método o sintaxis lambda) no parece lo suficientemente vago, 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 coherente 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 usar la sintaxis 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 son los operadores adicionales que se ofrecen como Saltar y Tomar. Por ejemplo, si está creando un método de paginación, es fácil implementar los primeros 10 registros y tomar los siguientes 10.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top