Compartir a través de


Relaciones de tipo en operaciones de consulta LINQ (C#)

Para escribir consultas de forma eficaz, debe comprender cómo los tipos de las variables de una operación de consulta completa se relacionan entre sí. Si comprende estas relaciones, comprenderá más fácilmente los ejemplos de LINQ y los ejemplos de código de la documentación. Además, comprenderá lo que ocurre cuando las variables se escriben implícitamente mediante var.

Las operaciones de consulta LINQ están fuertemente tipadas en el origen de datos, en la propia consulta y en la ejecución de la consulta. El tipo de las variables de la consulta debe ser compatible con el tipo de los elementos del origen de datos y con el tipo de la variable de iteración en la foreach instrucción . Esta escritura segura garantiza que los errores de tipo se detectan en tiempo de compilación cuando se pueden corregir antes de que los usuarios los encuentren.

Para demostrar estas relaciones de tipo, la mayoría de los ejemplos que siguen usan la escritura explícita para todas las variables. En el último ejemplo se muestra cómo se aplican los mismos principios incluso cuando se usa la escritura implícita mediante var.

Consultas que no transforman los datos de origen

En la ilustración siguiente se muestra una operación de consulta LINQ to Objects que no realiza ninguna transformación en los datos. El origen contiene una secuencia de cadenas y la salida de la consulta también es una secuencia de cadenas.

Diagrama que muestra la relación de los tipos de datos en una consulta LINQ.

  1. El argumento type del origen de datos determina el tipo de la variable de intervalo.
  2. El tipo del objeto seleccionado determina el tipo de la variable de consulta. Esta name es una cadena. Por lo tanto, la variable de consulta es .IEnumerable<string>
  3. La variable de consulta se procesa en iteración en la instrucción foreach. Dado que la variable de consulta es una secuencia de cadenas, la variable de iteración también es una cadena.

Consultas que transforman los datos de origen

En la ilustración siguiente se muestra una operación de consulta LINQ to SQL que realiza una transformación sencilla en los datos. La consulta toma una secuencia de Customer objetos como entrada y selecciona solo la Name propiedad en el resultado. Dado que Name es una cadena, la consulta genera una secuencia de cadenas como salida.

Diagrama que muestra una consulta que transforma el tipo de datos.

  1. El argumento type del origen de datos determina el tipo de la variable de intervalo.
  2. La instrucción select devuelve la propiedad Name, en lugar del objeto completo Customer. Dado que Name es una cadena, el argumento de tipo de custNameQuery es string, no Customer.
  3. Dado que custNameQuery es una secuencia de cadenas, la foreach variable de iteración del bucle también debe ser .string

En la ilustración siguiente se muestra una transformación ligeramente más compleja. La instrucción select devuelve un tipo anónimo que solo captura dos miembros del objeto original Customer.

Diagrama que muestra una consulta más compleja que transforma el tipo de datos.

  1. El argumento type del origen de datos es siempre el tipo de la variable de intervalo en la consulta.
  2. Dado que la select instrucción genera un tipo anónimo, la variable de consulta debe escribirse implícitamente mediante var.
  3. Dado que el tipo de la variable de consulta es implícito, la variable de iteración del foreach bucle también debe ser implícita.

Permitir que el compilador infera información de tipo

Aunque debe comprender las relaciones de tipo en una operación de consulta, tiene la opción de permitir que el compilador realice todo el trabajo. La palabra clave var se puede usar para cualquier variable local en una operación de consulta. La ilustración siguiente es similar al número de ejemplo 2 que se ha analizado anteriormente. Sin embargo, el compilador proporciona el tipo seguro para cada variable de la operación de consulta.

Diagrama que muestra el flujo de tipo con escritura implícita.

LINQ y tipos genéricos (C#)

Las consultas LINQ se basan en tipos genéricos. No necesita un conocimiento detallado de genéricos antes de empezar a escribir consultas. Sin embargo, es posible que quiera comprender dos conceptos básicos:

  1. Cuando se crea una instancia de una clase de colección genérica como List<T>, se reemplaza "T" por el tipo de objetos que contendrá la lista. Por ejemplo, una lista de cadenas se expresa como List<string>y una lista de Customer objetos se expresa como List<Customer>. Las listas genéricas están fuertemente tipadas y ofrecen muchas ventajas respecto a las colecciones que almacenan sus elementos como Object. Si intenta agregar un Customer a un List<string> elemento, obtendrá un error en tiempo de compilación. Usar colecciones genéricas es fácil porque no es necesario efectuar ninguna conversión de tipos en tiempo de ejecución.
  2. IEnumerable<T> es la interfaz que permite enumerar clases de colección genéricas mediante la foreach instrucción . Las clases de colección genéricas admiten IEnumerable<T> al igual que las clases de colección no genéricas, como ArrayList admiten IEnumerable.

Para obtener más información sobre los genéricos, vea Genéricos.

Variables IEnumerableT<> en consultas LINQ

Las variables de consulta LINQ se escriben como IEnumerable<T> o un tipo derivado como IQueryable<T>. Cuando vea una variable de consulta que se escribe como IEnumerable<Customer>, simplemente significa que la consulta, cuando se ejecuta, generará una secuencia de cero o más Customer objetos.

IEnumerable<Customer> customerQuery = from cust in customers
                                      where cust.City == "London"
                                      select cust;

foreach (Customer customer in customerQuery)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

Permitir que el compilador controle las declaraciones de tipos genéricos

Si lo prefiere, puede evitar la sintaxis genérica mediante la palabra clave var . La var palabra clave indica al compilador que infiera el tipo de una variable de consulta examinando el origen de datos especificado en la from cláusula . En el ejemplo siguiente se genera el mismo código compilado que el ejemplo anterior:

var customerQuery2 = from cust in customers
                     where cust.City == "London"
                     select cust;

foreach(var customer in customerQuery2)
{
    Console.WriteLine($"{customer.LastName}, {customer.FirstName}");
}

La var palabra clave es útil cuando el tipo de la variable es obvio o cuando no es tan importante especificar explícitamente tipos genéricos anidados, como los generados por consultas de grupo. En general, se recomienda que, si usa var, tenga en cuenta que puede dificultar la lectura del código. Para obtener más información, vea Variables locales con tipo implícito.