2010-02-02 16 views
31

Estoy aprendiendo C#, y me parece LINQ absolutamente interesante. Sin embargo, lo que me deja boquiabierto es que no puedo pensar en un escenario en el que usar LINQ sea una ayuda inmensa, ya que realmente no es tan difícil replicar las funciones de LINQ en el código.¿Cuándo debería usar LINQ para C#?

¿Alguna experiencia o sugerencia personal que quizás quieras compartir?

Gracias!

+0

Hay un voto para cerrar por razones de "subjetivo y argumentativo". Eso es idiota! Esta es una pregunta simple sobre el valor único de Linq. (Por otro lado, seguramente es una pregunta muy duplicada sobre SO, por lo que podría cerrarse por ese motivo.) –

+0

Estoy dispuesto a apostar que son votos "wiki o cercanos". Es subjetivo, por lo que probablemente debería ser una pregunta wiki. – Greg

+0

Gracias Earwicker. Solo tenía curiosidad, no entiendo por qué la gente piensa que esto es una razón subjetiva. No sabía que preguntar cómo codificar en una función sería subjetivo. La comunidad estos días. Tsk. – nubela

Respuesta

18

Me parece que estoy usando LINQ casi en cualquier momento que hubiera escrito previamente un bucle para llenar un contenedor. Uso LINQ to SQL como mi ORM y muchos LINQ en todos lados.

Aquí hay un pequeño fragmento que escribí para una clase de ayuda de Active Directory que descubre si un usuario en particular es un grupo en particular. Tenga en cuenta el uso del método Any() para iterar sobre los grupos de autorización del usuario hasta que encuentre uno con un SID coincidente. Código mucho más limpio que la alternativa.

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 
    return user.GetAuthorizationGroups() 
       .Any(g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0); 
} 

Alternativa:

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 
    bool inGroup = false; 
    foreach (var g in user.GetAuthorizationGroups()) 
    { 
     if (g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0) 
     { 
      inGroup = true; 
      break; 
     } 
    } 
    return inGroup; 
} 

o

private bool IsInGroup(GroupPrincipal group, UserPrincipal user) 
{ 
    if (group == null || group.Sid == null) 
    { 
     return false; 
    } 

    foreach (var g in user.GetAuthorizationGroups()) 
    { 
     if (g => g.Sid != null && g.Sid.CompareTo(group.Sid) == 0) 
     { 
      return true; 
     } 
    } 
    return false; 
} 

He aquí un fragmento que hace una búsqueda en un repositorio, órdenes, y convierte los primeros 10 objetos de negocio a juego en una vista específica el modelo (Distance es la distancia de edición de Levenshtein de la ID única del modelo coincidente del parámetro uniqueID).

model.Results = this.Repository.FindGuestByUniqueID(uniqueID, withExpired) 
           .OrderBy(g => g.Distance) 
           .Take(10) 
           .ToList() 
           .Select(g => new GuestGridModel(g)); 
+2

Interesante, elaboración sobre el ciclo/llenado ¿un contenedor? Algunas muestras de código? – nubela

+0

Estrictamente hablando, esto no se trata tanto de usar LINQ como de utilizar los métodos de extensión a los que convierte la sintaxis LINQ. Solo me resulta más fácil leer el estilo fluido, menos disonancia cognitiva al ir y venir con jQuery. Sin duda, podría representar todo lo anterior utilizando la sintaxis LINQ. – tvanfosson

+1

Eh, si está en el espacio de nombres System.Linq, creo que cuenta como usar LINQ, independientemente de la sintaxis con la que lo llame. –

12

Encuentro LINQ útil cuando tengo una colección de algún objeto y me interesan los artículos que cumplen ciertos criterios. Un ejemplo simple sería buscar todas las formas en una colección de formas que son círculos.

var circles = 
     from s in allShapes 
     where s.Type == ShapeTypes.Circle 
     select s; 

admito Me podría haber escrito un bucle con un poco de código en él, pero encuentro este código más corto y más fácil de escribir, y más fácil de leer y entender.

LINQ también se puede utilizar con bases de datos, pero en realidad creo que no hago mucho eso. Para cada uno, supongo.

4

Uso LINQ to DataSet mucho para trabajar con DataTables. Las tablas de datos son almacenamientos de datos genéricos donde a menudo almaceno valores, por ej. desde un archivo CSV cargado. Es mucho más legible y cómodo usar LINQ para consultar o unir datos en lugar de "fuerza bruta" -ing con for-loops.

0

Para mí, casi solo lo uso para acceder a las bases de datos. Casi nunca consulto en XML o en la lista.

2

Sí, puede usar LINQ to Objects fácilmente con un código alternativo, y no es tan difícil. Tiendo a gustarme de la semántica de las expresiones lambda, y envuelve varias líneas de código en una. Pero puede hacer muchas operaciones con su propio código, excepto que algunas de las operaciones más grandes (unión, intersección, etc.) son más fáciles de hacer con LINQ.

LINQ tiene otros sabores; LINQ to XML hace que sea realmente agradable trabajar con datos XML. Realmente me gusta más que los objetos anteriores disponibles.

LINQ to SQL y ADO.NET Entity Framework (con LINQ to Entities) es un asignador relacional de objetos y puede mapear a las tablas de su base de datos, y actuar como procedimientos almacenados y ADO.Los conjuntos de datos NET, sí, por lo que es una muy buena alternativa que los conjuntos de datos/tablas de datos débiles, y también me gusta en conjuntos de datos/tablas fuertemente tipados.

HTH.

+0

Voto a favor de intersección/menciones de unión.Aquí también es donde encuentro que LINQ tiene el mayor beneficio :) Además de eso, a menudo documenta la intención mejor que los bucles foreach. –

0

Encuentro útil transformar/"proyectar" datos antes de vincularlos a una grilla con fines de solo lectura.

0

El conjunto de características del lenguaje LINQ no se puede replicar tan fácilmente en el código C# 2.0, sin métodos de extensión, expresiones lambda e incluso sin los operadores de consulta. El objetivo de LINQ es que tenga alguna versión integrada de consultas en la que use el compilador para verificar su cordura. El otro punto crucial es la unificación de la vista en diferentes fuentes de datos, ya sea una base de datos o una colección en memoria. Puede vivir sin LINQ, del mismo modo que puede vivir sin ninguna otra característica del lenguaje y el código en Assembler, pero existen ventajas obvias que son difíciles de supervisar;)

6

Tiene razón, rara vez es muy difícil de replicar las características en C# normal. Es lo que ellos llaman azúcar sintáctico. Es solo por conveniencia. ¿Conoces las propiedades automáticas? Los que le permiten escribir public class User { public int Id { get; set; } } Eso es extremadamente fácil de replicar en el código "normal" de C#. Aun así, las propiedades automáticas siguen siendo impresionantes;)

El filtrado y la clasificación son prácticamente el núcleo de LINQ. Considere que tiene una lista de usuarios, llamada, bueno, users, y quiere encontrar a los que han iniciado sesión hoy, y mostrarlos en orden de inicio de sesión más reciente. Antes de LINQ, probablemente haría algo así como crear un nueva lista, que completa según la lista original, iterándola, agregando lo que cumple con los criterios y luego implementando algún tipo de IComparable. Ahora usted puede hacer:

users = users.Where(u => u.LastLoggedIn.Date = DateTime.Today) 
      .OrderBy(u => u.LastLoggedIn).ToList(); 

Conveniencia =)

+1

conveniencia y legibilidad! –

+1

¿Y por qué incluso llamar a .ToList()? 9 veces de cada 10 no es necesario y puede matar tu rendimiento. –

+0

estaré de acuerdo con eso, pero mi ejemplo asumió una lista de usuarios, según el texto anterior. concedido, fácilmente podría haber cambiado mi ejemplo =) –

10

El libro Essential LINQ proporciona un gran resumen de un párrafo del beneficio de LINQ:

LINQ hace más que simplemente añadir nuevas características al lenguaje Es introduce un estilo delcarativo de la programación en el lenguaje C#. El modelo de programación declarativa permite a los desarrolladores a las embarcaciones de código que captura succictly su intención, sin forzarlos a preocuparse por el orden en que los eventos tienen lugar, o su aplicación precisa. Es permite a los desarrolladores indicar lo que quieren hacer, en lugar de cómo va a ser hecho.

14

Depende de qué tipo de LINQ que quiere decir.

¿Es linq-to-sql? En ese caso, es un orm con todos los mismos beneficios que se obtienen al usar cualquier otro orm. No lo uso mucho y realmente no puedo decir más.

¿Es linq-to-objects? En ese caso, realmente está hablando de una colección de otras cosas: métodos de extensión, iteradores perezosos y una sintaxis de comprensión de consultas.Es una introducción al mundo de la programación funcional. No tengo mucho uso para la sintaxis de comprensión de consultas, pero para el resto, puedo demostrar mejor con un ejemplo.

Digamos que usted quiere leer un archivo en línea por línea. Para cada línea, que desea comprobar si cumple con algunos criterios, convertir una porción de esas líneas a un entero, y resumir la primera 10 de esos números enteros que son también dentro de un cierto rango. Aquí está la vieja manera que haría que:

int SumXValues(string filename) 
{ 
    string line; 
    int sum = 0; 
    int count = 0; 
    using (var rdr = new StreamReader(filename)) 
    { 

     while ((line = rdr.ReadLine()) != null && count < 10) 
     { 
      int val; 
      if (int.TryParse(line.Substring(3,3)) 
      { 
       if (val > 4 && val < 25) 
       { 
        sum += val; 
        count ++; 
       } 
      } 
     } 
    } 
    return sum; 
} 

Aquí está la nueva forma:

IEnumerable<string> ReadLines(string filename) 
{ 
    string line; 
    using (var rdr = new StreamReader(filename)) 
     while ((line = rdr.ReadLine()) != null) 
      yield return line; 
} 

int SumXValues(string filename) 
{ 
    return ReadLines(filename) 
       .Select(l => l.Substring(3,3)) 
       .Where(l => int.TryParse(l)) 
       .Select(i => int.Parse(i)) 
       .Where(i => i > 4 && i < 16) 
       .Take(10) 
       .Sum(i => i); 
} 

Aviso el nuevo código es en realidad más corto. Pero ¿por qué también es mejor ? Hay (al menos) 4 razones:

  • Esperemos que sea evidente la forma reutilizable es la función readlines. También podría factorizar más, pero el objetivo es mostrar cómo este estilo le ayuda a reutilizar más código.
  • se escala mejor. Observe todas las llamadas a funciones encadenadas en esa última función. ¿Sabes cuántas veces ese código iterará sobre las líneas en tu archivo? ¡Exactamente una vez! De hecho, ni siquiera eso, ya que dejará de leer el archivo después de tomar los primeros 10 elementos. ¿Y si lo cambia para devolver un enumerable y luego usarlo en otro lugar con otros métodos de extensión? ¡Solo una vez! Esto le permite crear, mezclar y remezclar sus resultados de la consulta en tiempo de ejecución sin pases adicionales costosos en sus listas.
  • es más fácil de mantener. Si el criterio cambia, es fácil detectar la "regla" exacta (si lo desea) que le interese y modificar solo esa parte.
  • es más legible. Esto le permite expresar el código en términos de lo que está haciendo en lugar de cómo lo hace.
+0

+! Buen ejemplo, buenas razones – Zyphrax

3

Me gustaría dar la vuelta a la pregunta: ¿puede mostrarnos cómo emularía las características de Linq sin ella? Tengo problemas para pensar en un caso en el que no es una ayuda inmensa.

Por ejemplo, vi algo como esto recientemente:

foreach (var person in people.OrderBy(p => p.Company) 
          .ThenBy(p => p.LastName) 
          .ThenBy(p => p.FirstName)) { 
    ... 
} 

supongo que podría haber utilizado Arrays.Sort, creado un delegado que comprueba los campos en el orden correcto, y (hacia atrás desde escrito, ¿verdad?) luego solo viví con el hecho de que solo funcionaría en Arrays. Parece que sería mucho más tiempo, más difícil de mantener y menos flexible.

0

Un punto más para agregar a todo lo que es un tipo de punto de resumen. Puede ver desde arriba que se usa por conveniencia y brevedad y se puede usar con colecciones, SQL, XML (y cualquier otra cosa que se preocupe por implementar un proveedor LINQ), pero lo mejor de todo es que solo tiene que aprender la sintaxis LINQ una vez. lleva a todas esas áreas de tecnología útil.

1

Eche un vistazo a ReSharper si aún no lo ha hecho. Tiene muchos consejos para "... convertir a sintaxis LINQ", por lo que generalmente puede mostrarle una o dos cosas que no consideró al aprender. :)

1

Alguien mencionó que LINQ es un estilo declarativo de programación. Solo quería expandirme sobre eso.

Una forma en que uso LINQ es escribir el código de prueba de Oracle.Es muy importante que el código de prueba sea simple y lo más cercano a "obviamente correcto" como sea posible, o de lo contrario terminará con tantos errores como el código que se supone que debe probar. Con una característica particular que estoy probando ahora, escribí una pequeña lista de conjuntos de comprensiones que describen exactamente cómo espero que funcione la característica. Gracias a LINQ, convertir esas comprensiones de código se convierte en trivialmente fácil:

A = all items 
B = [x in A: x.Type = selectedtype, x.Source = "sourceA"] 
C = [x in A: x.Source = "sourceB"] 
D = B union C 

En código:

IEnumerable<MyClass> SetB(IEnumerable<MyClass> allItems, MyType type) 
{ 
    var result = from item in allItems 
       where item.Type == type && item.Source == "sourceA" 
       select item; 
    return result; 
} 

IEnumerable<MyClass> SetC(IEnumerable<MyClass> allItems) 
{ 
    var result = from item in allItems 
       where item.Source == "sourceB" 
       select item; 
    return result; 
} 

IEnumerable<MyClass> SetD(IEnumerable<MyClass> allItems, MyType type) 
{ 
    var setB = SetB(allItems, type); 
    var setC = SetC(allItems); 
    return setB.Union(setC); 
} 

Aunque todavía un poco más detallado que las expresiones matemáticas, que es mucho más simple y más fácil llamar " obviamente correcto "que el código imperativo sería. El código LINQ es declarativo, como que la matemática es declarativa. Menos traducción, más cerca de la especificación. LINQ, cuando se usa apropiadamente, es más o menos un lenguaje de "Haz lo que quiero decir".

Tenga en cuenta que no escribiría el código actual de esta manera. El rendimiento no es un requisito para el código de prueba, pero es para el código real, por lo que el código real aún necesita ser un procedimiento almacenado SQL.

Cuestiones relacionadas