Compartir vía


Relaciones de tipos en operaciones de consulta (Visual Basic)

Las variables usadas en las operaciones de consulta de Language-Integrated Query (LINQ) están fuertemente tipadas y deben ser compatibles entre sí. La escritura segura se usa en el origen de datos, en la propia consulta y en la ejecución de la consulta. En la ilustración siguiente se identifican los términos usados para describir una consulta LINQ. Para obtener más información sobre las partes de una consulta, vea Operaciones de consulta básicas (Visual Basic).

Captura de pantalla que muestra una consulta de pseudocódigo con elementos resaltados.

El tipo de la variable de rango de la consulta debe ser compatible con el tipo de los elementos del origen de datos. El tipo de la variable de consulta debe ser compatible con el elemento de secuencia definido en la Select cláusula . Por último, el tipo de los elementos de secuencia también debe ser compatible con el tipo de la variable de control de bucle que se usa en la For Each instrucción que ejecuta la consulta. Esta escritura fuerte facilita la identificación de errores de tipo en tiempo de compilación.

Visual Basic facilita la escritura segura mediante la implementación de la inferencia de tipos locales, también conocida como escritura implícita. Esa característica se usa en el ejemplo anterior y verá que se usa en los ejemplos y la documentación de LINQ. En Visual Basic, la inferencia de tipo local se lleva a cabo simplemente usando una Dim instrucción sin una As cláusula. En el ejemplo siguiente, city se escribe fuertemente como una cadena.

Dim city = "Seattle"

Nota:

La inferencia de tipos locales solo funciona cuando Option Infer se establece en On. Para obtener más información, vea Option Infer Statement.

Sin embargo, aunque use la inferencia de tipos locales en una consulta, las mismas relaciones de tipo están presentes entre las variables del origen de datos, la variable de consulta y el bucle de ejecución de consultas. Resulta útil tener un conocimiento básico de estas relaciones de tipo al escribir consultas LINQ o trabajar con los ejemplos y ejemplos de código de la documentación.

Es posible que tenga que especificar un tipo explícito para una variable de intervalo que no coincida con el tipo devuelto desde el origen de datos. Puede especificar el tipo de la variable de intervalo mediante una As cláusula . Sin embargo, esto produce un error si la conversión es una conversión de restricción y Option Strict se establece en On. Por lo tanto, se recomienda realizar la conversión en los valores recuperados del origen de datos. Puede convertir los valores del origen de datos al tipo de variable de intervalo explícito mediante el Cast método . También puede convertir los valores seleccionados en la Select cláusula a un tipo explícito diferente del tipo de la variable de intervalo. Estos puntos se muestran en el código siguiente.

Dim numbers1() As Integer = {1, 2, 4, 16, 32, 64}
Dim numbers2() As Double = {5.0#, 10.0#, 15.0#}

' This code does not result in an error.
Dim numberQuery1 = From n As Integer In numbers1 Where n > 5

' This code results in an error with Option Strict set to On. The type Double
' cannot be implicitly cast as type Integer.
Dim numberQuery2 = From n As Integer In numbers2 Where n > 5

' This code casts the values in the data source to type Integer. The type of
' the range variable is Integer.
Dim numberQuery3 = From n In numbers2.Cast(Of Integer)() Where n > 5

' This code returns the value of the range variable converted to Integer. The type of
' the range variable is Double.
Dim numberQuery4 = From n In numbers2 Where n > 5 Select CInt(n)

Consultas que devuelven elementos completos de los datos de origen

En el ejemplo siguiente se muestra una operación de consulta LINQ que devuelve una secuencia de elementos seleccionados a partir de los datos de origen. El origen, names, contiene una matriz de cadenas y la salida de la consulta es una secuencia que contiene cadenas que comienzan con la letra M.

Dim names = {"John", "Rick", "Maggie", "Mary"}
Dim mNames = From name In names
             Where name.IndexOf("M") = 0
             Select name

For Each nm In mNames
    Console.WriteLine(nm)
Next

Esto equivale al código siguiente, pero es mucho más corto y fácil de escribir. La dependencia de la inferencia de tipos locales en las consultas es el estilo preferido en Visual Basic.

Dim names2 = {"John", "Rick", "Maggie", "Mary"}
Dim mNames2 As IEnumerable(Of String) =
    From name As String In names
    Where name.IndexOf("M") = 0
    Select name

For Each nm As String In mNames
    Console.WriteLine(nm)
Next

Las siguientes relaciones existen en ambos ejemplos de código anteriores, tanto si los tipos se determinan implícita o explícitamente.

  1. El tipo de los elementos del origen de datos, names, es el tipo de la variable de intervalo, name, en la consulta.

  2. El tipo del objeto seleccionado, name, determina el tipo de la variable de consulta, mNames. Esta name es una cadena, por lo que la variable de consulta es IEnumerable(Of String) en Visual Basic.

  3. La consulta definida en mNames se ejecuta en el For Each bucle . El bucle recorre en iteración el resultado de ejecutar la consulta. Dado mNames, cuando se ejecuta, devolverá una secuencia de cadenas, la variable de iteración del bucle, nm, también es de tipo cadena.

Consultas que devuelven un campo de los elementos seleccionados

En el ejemplo siguiente se muestra una operación de consulta LINQ to SQL que devuelve una secuencia que contiene solo una parte de cada elemento seleccionado del origen de datos. La consulta utiliza una colección de objetos como fuente de datos y proyecta únicamente la propiedad Customer en el resultado. Dado que el nombre del cliente es una cadena, la consulta genera una secuencia de cadenas como salida.

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim custNames = From cust In customers
                Where cust.City = "London"
                Select cust.Name

For Each custName In custNames
    Console.WriteLine(custName)
Next

Las relaciones entre variables son similares a las del ejemplo más sencillo.

  1. El tipo de los elementos del origen de datos, customers, es el tipo de la variable de intervalo, cust, en la consulta. En este ejemplo, ese tipo es Customer.

  2. La Select instrucción devuelve la Name propiedad de cada Customer objeto en lugar del objeto completo. Dado que Name es una cadena, la variable de consulta, custNames, volverá a ser IEnumerable(Of String), no de Customer.

  3. Dado que custNames representa una secuencia de cadenas, la For Each variable de iteración del bucle , custName, debe ser una cadena.

Sin la inferencia de tipos locales, el ejemplo anterior sería más complicado escribir y comprender, como se muestra en el ejemplo siguiente.

' Method GetTable returns a table of Customer objects.
 Dim customers As Table(Of Customer) = db.GetTable(Of Customer)()
 Dim custNames As IEnumerable(Of String) =
     From cust As Customer In customers
     Where cust.City = "London"
     Select cust.Name

 For Each custName As String In custNames
     Console.WriteLine(custName)
 Next

Consultas que requieren tipos anónimos

En el ejemplo siguiente se muestra una situación más compleja. En el ejemplo anterior, era inconveniente especificar tipos para todas las variables explícitamente. En este ejemplo, es imposible. En lugar de seleccionar elementos completos Customer del origen de datos o un único campo de cada elemento, la Select cláusula de esta consulta devuelve dos propiedades del objeto original Customer : Name y City. En respuesta a la Select cláusula , el compilador define un tipo anónimo que contiene esas dos propiedades. El resultado de ejecutar nameCityQuery en el bucle For Each es una colección de instancias del nuevo tipo anónimo. Dado que el tipo anónimo no tiene ningún nombre utilizable, no puede especificar el tipo de nameCityQuery o custInfo explícitamente. Es decir, con un tipo anónimo, no tiene ningún nombre de tipo para usar en lugar de String en IEnumerable(Of String). Para obtener más información, consulte Tipos anónimos (Guía de programación de C#).

' Method GetTable returns a table of Customer objects.
Dim customers = db.GetTable(Of Customer)()
Dim nameCityQuery = From cust In customers
                    Where cust.City = "London"
                    Select cust.Name, cust.City

For Each custInfo In nameCityQuery
    Console.WriteLine(custInfo.Name)
Next

Aunque no es posible especificar tipos para todas las variables del ejemplo anterior, las relaciones siguen siendo las mismas.

  1. El tipo de los elementos del origen de datos es de nuevo el tipo de la variable de intervalo en la consulta. En este ejemplo, cust es una instancia de Customer.

  2. Dado que la Select instrucción genera un tipo anónimo, la variable de consulta, nameCityQuery, debe escribirse implícitamente como un tipo anónimo. Un tipo anónimo no tiene ningún nombre utilizable y, por tanto, no se puede especificar explícitamente.

  3. El tipo de la variable de iteración en el For Each bucle es el tipo anónimo creado en el paso 2. Dado que el tipo no tiene ningún nombre utilizable, el tipo de la variable de iteración de bucle se debe determinar implícitamente.

Consulte también