Compartir a través de


Relaciones entre tipos en operaciones de consulta (Visual Basic)

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

Partes de una consulta LINQ

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 cláusula Select. Finalmente, el tipo de los elementos de secuencia también debe ser compatible con el tipo de la variable de control del bucle que se utiliza en la instrucción For Each que ejecuta la consulta. Este tipado fuerte facilita la identificación de los errores de tipos en tiempo de compilación.

Visual Basic simplifica el tipado fuerte al implementar la inferencia de tipo de variable local, lo que también se conoce como tipo implícito. Esta característica se utiliza en el ejemplo anterior y, como observará, se utiliza en los ejemplos y la documentación de LINQ. En Visual Basic, la inferencia de tipo de variable local se consigue simplemente utilizando una instrucción Dim sin una cláusula As. En el ejemplo siguiente, city está fuertemente tipado como cadena.

Dim city = "Seattle"
NotaNota

La inferencia de tipo de variable local sólo funciona cuando Option Infer se establece en On.Para obtener más información, consulte Option Infer (instrucción).

Sin embargo, aun cuando se utiliza la inferencia de tipo de variable local en una consulta, las mismas relaciones de tipo se encuentran entre las variables del origen de datos, la variable de consulta y el bucle de ejecución de la consulta. Es útil conocer los fundamentos de estas relaciones de tipos para escribir consultas LINQ o trabajar con los ejemplos y ejemplos de código de la documentación.

Puede que tenga que especificar un tipo explícito para una variable de rango que no coincide con el tipo devuelto por el origen de datos. Puede especificar el tipo de la variable de rango mediante una cláusula As. Sin embargo, esto hace que se produzca un error si se trata de una conversión de restricción y Option Strict se ha establecido en On. Por consiguiente, se recomienda realizar la conversión en los valores recuperados del origen de datos. Puede convertir los valores del origen de datos en el tipo de variable de rango explícito con el método Cast``1. También puede convertir los valores seleccionados en la cláusula Select en un tipo explícito distinto al de la variable de rango. Estos puntos se reflejan 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 de los datos de origen. El origen, names, contiene una matriz de cadenas y el resultado de la consulta es una secuencia que contiene cadenas que empiezan por 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

Es equivalente al código siguiente, pero es mucho más corto y más fácil de escribir. En Visual Basic, se prefiere la inferencia de tipo de variable local en las consultas.

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

En los dos ejemplos de código anteriores existen las siguientes relaciones, se determinen los tipos de forma implícita o explícita.

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

  2. El tipo de objeto seleccionado, name, determina el tipo de la variable de consulta, mNames. Aquí 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 bucle For Each El bucle recorre en iteración el resultado de ejecutar la consulta. Dado que mNames, cuando se ejecuta, devuelve una secuencia de cadenas, la variable de iteración del bucle, nm, también es una 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 sólo una parte de cada elemento seleccionado del origen de datos. La consulta utiliza una colección de objetos Customer como origen de datos y proyecta sólo la propiedad Name en el resultado. Dado que el nombre del cliente es una cadena, la consulta genera una secuencia de cadenas como resultado.

' 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 las variables son como las del ejemplo más sencillo.

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

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

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

Sin la inferencia de tipo de variable local, el ejemplo anterior sería más difícil de escribir y de entender, como demuestra 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, no era apropiado especificar explícitamente los tipos de todas las variables. En este ejemplo, no se puede. En lugar de seleccionar los elementos Customer completos del origen de datos o un campo único de cada elemento, la cláusula Select de esta consulta devuelve dos propiedades del objeto Customer original: Name y City. Como respuesta a la cláusula Select, 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 explícitamente el tipo de nameCityQuery o custInfo. Es decir, con un tipo anónimo, no hay ningún nombre de tipo que se pueda utilizar en lugar de String en IEnumerable(Of String). Para obtener más información, vea Tipos anónimos (Visual Basic).

' 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 los tipos de todas las variables en el 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 rango de la consulta. En este ejemplo, cust es una instancia de Customer.

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

  3. El tipo de la variable de iteración en el bucle For Each 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 del bucle se debe determinar implícitamente.

Vea también

Conceptos

Tipos anónimos (Visual Basic)

Inferencia de tipo de variable local (Visual Basic)

Introducción a LINQ en Visual Basic

Otros recursos

Introducción a LINQ en Visual Basic

LINQ en Visual Basic

Consultas de Visual Basic