Cómo: Escribir consultas con LINQ en C#

En este tema se muestran las tres formas en que se puede escribir una consulta LINQ en C#:

  1. Mediante la sintaxis de consulta.

  2. Mediante la sintaxis de método.

  3. Mediante una combinación de sintaxis de consulta y sintaxis de método.

En los ejemplos siguientes se muestran algunas consultas LINQ sencillas con cada uno de los procedimientos enumerados anteriormente. La regla general consiste en utilizar (1) siempre que sea posible y utilizar (2) y (3) cuando sea necesario.

NotaNota

Estas consultas funcionan en colecciones en memoria simples; sin embargo, la sintaxis básica es idéntica a la que se utiliza en LINQ to SQL y LINQ to XML.

Ejemplo

Sintaxis de consulta

La forma recomendada de escribir la mayoría de las consultas es utilizar la sintaxis de consulta para crear expresiones de consulta. En el ejemplo siguiente se muestran tres expresiones de consulta. La primera expresión de consulta muestra cómo filtrar o restringir los resultados aplicando condiciones con una cláusula where. Devuelve todos los elementos de la secuencia de origen cuyos valores son mayores que 7 o menores que 3. La segunda expresión muestra cómo ordenar los resultados devueltos. La tercera expresión muestra cómo agrupar los resultados según una clave. Esta consulta devuelve dos grupos basándose en la primera letra de la palabra.

// Query #1.
List<int> numbers = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

// The query variable can also be implicitly typed by using var
IEnumerable<int> filteringQuery =
    from num in numbers
    where num < 3 || num > 7
    select num;

// Query #2.
IEnumerable<int> orderingQuery =
    from num in numbers
    where num < 3 || num > 7
    orderby num ascending 
    select num;

// Query #3. 
string[] groupingQuery = { "carrots", "cabbage", "broccoli", "beans", "barley" };
IEnumerable<IGrouping<char, string>> queryFoodGroups =
    from item in groupingQuery
    group item by item[0];

Observe que el tipo de las consultas es IEnumerable. Todas estas consultas podrían escribirse utilizando var, tal y como se muestra en el ejemplo siguiente:

var query = from num in numbers...

En cada uno de los ejemplos anteriores, las consultas no se ejecutan realmente hasta que se procesa una iteración de la variable de consulta en una instrucción foreach. Para obtener más información, vea Introducción a las consultas LINQ (C#).

Sintaxis de método

Algunas operaciones de consulta deben expresarse como una llamada a un método. Los métodos más habituales de este tipo son aquellos que devuelven valores numéricos singleton, como Sum, Max, Min, Average, etc. Siempre se debe llamar a estos métodos en último lugar en cualquier consulta porque representan un solo valor y no sirven como origen de una operación de consulta adicional. En el ejemplo siguiente se muestra una llamada a un método en una expresión de consulta:

List<int> numbers1 = new List<int>() { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
List<int> numbers2 = new List<int>() { 15, 14, 11, 13, 19, 18, 16, 17, 12, 10 };
// Query #4. 
double average = numbers1.Average();

// Query #5.
IEnumerable<int> concatenationQuery = numbers1.Concat(numbers2);

Si el método incluye parámetros, éstos se proporcionan en forma de expresión lambda, tal y como se muestra en el ejemplo siguiente:

// Query #6.
IEnumerable<int> largeNumbersQuery = numbers2.Where(c => c > 15);

De todas las consultas anteriores, sólo la número 4 se ejecuta inmediatamente. Esto se debe a que devuelve un solo valor y no una colección IEnumerable genérica. El propio método tiene que usar foreach para calcular su valor.

Cada una de las consultas anteriores puede escribirse usando tipos implícitos con var, tal y como se muestra en el ejemplo siguiente:

// var is used for convenience in these queries 
var average = numbers1.Average();
var concatenationQuery = numbers1.Concat(numbers2);
var largeNumbersQuery = numbers2.Where(c => c > 15);

Sintaxis mixta de consulta y método

En este ejemplo se muestra cómo usar la sintaxis de método en los resultados de una cláusula de consulta. Simplemente hay que incluir la expresión de consulta entre paréntesis y, a continuación, aplicar el operador de punto y llamar al método. En el ejemplo siguiente, la consulta número 7 devuelve un recuento de los números cuyo valor se encuentra comprendido entre 3 y 7. Sin embargo, en general es mejor utilizar una segunda variable para almacenar el resultado de la llamada al método. De esta forma, es menos probable que la consulta se confunda con los resultados de la consulta.

// Query #7. 

// Using a query expression with method syntax 
int numCount1 =
    (from num in numbers1
     where num < 3 || num > 7
     select num).Count();

// Better: Create a new variable to store 
// the method call result
IEnumerable<int> numbersQuery =
    from num in numbers1
    where num < 3 || num > 7
    select num;

int numCount2 = numbersQuery.Count();

La consulta número 7 se ejecuta inmediatamente porque devuelve un solo valor y no una colección.

La consulta anterior puede escribirse usando tipos implícitos con var, de la siguiente forma:

var numCount = (from num in numbers...

Puede escribirse mediante la sintaxis de método, de la siguiente forma:

var numCount = numbers.Where(n => n < 3 || n > 7).Count();

Puede escribirse mediante tipos implícitos, de la siguiente forma:

int numCount = numbers.Where(n => n < 3 || n > 7).Count();

Vea también

Tareas

Tutorial: Escribir consultas en C# (LINQ)

Referencia

where (Cláusula, Referencia de C#)

Conceptos

Expresiones de consultas LINQ (Guía de programación de C#)

Otros recursos

LINQ (Language-Integrated Query)