Compartilhar via


Relações de tipo em operações de consulta (Visual Basic)

As variáveis usadas em operações de consulta LINQ (consulta integrada à linguagem) são fortemente tipadas e devem ser compatíveis entre si. A digitação forte é usada na fonte de dados, na própria consulta e na execução da consulta. A ilustração a seguir identifica os termos usados para descrever uma consulta LINQ. Para obter mais informações sobre as partes de uma consulta, consulte Operações básicas de consulta (Visual Basic).

Captura de tela mostrando uma consulta pseudocódigo com elementos realçados.

O tipo da variável de intervalo na consulta deve ser compatível com o tipo dos elementos na fonte de dados. O tipo da variável de consulta deve ser compatível com o elemento de sequência definido na Select cláusula. Por fim, o tipo de elementos de sequência também deve ser compatível com o tipo da variável de controle de loop usada na For Each instrução que executa a consulta. Essa tipagem forte facilita a identificação de erros de tipo em tempo de compilação.

O Visual Basic torna a tipagem forte conveniente implementando a inferência de tipo local, também conhecida como tipagem implícita. Esse recurso é usado no exemplo anterior e você o verá usado em todos os exemplos e documentação do LINQ. No Visual Basic, a inferência de tipo local é realizada simplesmente usando uma Dim instrução sem uma As cláusula. No exemplo a seguir, city é fortemente tipado como uma cadeia de caracteres.

Dim city = "Seattle"

Observação

A inferência de tipo local só funciona quando Option Infer é definida como On. Para obter mais informações, consulte Option Infer Statement.

No entanto, mesmo se você usar inferência de tipo local em uma consulta, as mesmas relações de tipo estarão presentes entre as variáveis na fonte de dados, a variável de consulta e o loop de execução da consulta. É útil ter uma compreensão básica dessas relações de tipo ao escrever consultas LINQ ou trabalhar com os exemplos e exemplos de código na documentação.

Talvez seja necessário especificar um tipo explícito para uma variável de intervalo que não corresponda ao tipo retornado da fonte de dados. Você pode especificar o tipo da variável de intervalo usando uma As cláusula. No entanto, isso resultará em um erro se a conversão for uma conversão de restrição e Option Strict for definida como On. Portanto, recomendamos que você execute a conversão nos valores recuperados da fonte de dados. Você pode converter os valores da fonte de dados para o tipo de variável de intervalo explícito usando o Cast método. Você também pode converter para um tipo explícito diferente do tipo da variável de alcance os valores selecionados na cláusula Select. Esses pontos são ilustrados no código a seguir.

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 retornam elementos inteiros dos dados de origem

O exemplo a seguir mostra uma operação de consulta LINQ que retorna uma sequência de elementos selecionados dos dados de origem. A origem names contém uma matriz de cadeias de caracteres e a saída da consulta é uma sequência que contém cadeias de caracteres que começam com a 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

Isso é equivalente ao código a seguir, mas é muito mais curto e fácil de escrever. A dependência da inferência de tipo local em consultas é o estilo preferencial no 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

As relações a seguir existem em ambos os exemplos de código anteriores, independentemente de os tipos serem determinados implicitamente ou explicitamente.

  1. O tipo dos elementos na fonte de dados, namesé o tipo da variável de intervalo, namena consulta.

  2. O tipo do objeto selecionado, namedetermina o tipo da variável de consulta. mNames Aqui name está uma cadeia de caracteres, portanto, a variável de consulta é IEnumerable(Of String) no Visual Basic.

  3. A consulta definida em mNames é executada no loop For Each. O loop itera sobre o resultado da execução da consulta. Porque mNames, quando executada, retornará uma sequência de cadeias de caracteres, a variável de iteração de loop, nmtambém é uma cadeia de caracteres.

Consultas que retornam um campo de elementos selecionados

O exemplo a seguir mostra uma operação de consulta LINQ to SQL que retorna uma sequência que contém apenas uma parte de cada elemento selecionado na fonte de dados. A consulta usa uma coleção de objetos como sua fonte de Customer dados e projeta apenas a Name propriedade no resultado. Como o nome do cliente é uma cadeia de caracteres, a consulta produz uma sequência de cadeias de caracteres como saída.

' 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

As relações entre variáveis são semelhantes às do exemplo mais simples.

  1. O tipo dos elementos na fonte de dados, customersé o tipo da variável de intervalo, custna consulta. Neste exemplo, esse tipo é Customer.

  2. A instrução Select devolve a propriedade Name de cada objeto Customer, em vez do objeto inteiro. Como Name é uma cadeia de caracteres, a variável custNamesde consulta será novamente IEnumerable(Of String), não de Customer.

  3. Como custNames representa uma sequência de cadeias de caracteres, a For Each variável custNamede iteração do loop deve ser uma cadeia de caracteres.

Sem inferência de tipo local, o exemplo anterior seria mais complicado de escrever e entender, como mostra o exemplo a seguir.

' 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 exigem tipos anônimos

O exemplo a seguir mostra uma situação mais complexa. No exemplo anterior, era inconveniente especificar tipos para todas as variáveis explicitamente. Neste exemplo, é impossível. Em vez de selecionar elementos inteiros Customer da fonte de dados ou um único campo de cada elemento, a Select cláusula nesta consulta retorna duas propriedades do objeto original Customer : Name e City. Em resposta à Select cláusula, o compilador define um tipo anônimo que contém essas duas propriedades. O resultado da execução nameCityQuery no For Each loop é uma coleção de instâncias do novo tipo anônimo. Como o tipo anônimo não tem nenhum nome utilizável, você não pode especificar o tipo de nameCityQuery nem de custInfo explicitamente. Ou seja, com um tipo anônimo, você não tem nenhum nome de tipo para usar no lugar de StringIEnumerable(Of String). Para obter mais informações, consulte Tipos Anônimos.

' 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

Embora não seja possível especificar tipos para todas as variáveis no exemplo anterior, as relações permanecem as mesmas.

  1. O tipo dos elementos na fonte de dados é novamente o tipo da variável de intervalo na consulta. Neste exemplo, cust é uma instância de Customer.

  2. Como a Select instrução produz um tipo anônimo, a variável nameCityQueryde consulta deve ser digitada implicitamente como um tipo anônimo. Um tipo anônimo não tem nenhum nome utilizável e, portanto, não pode ser especificado explicitamente.

  3. O tipo da variável de iteração no For Each loop é o tipo anônimo criado na etapa 2. Como o tipo não tem um nome utilizável, o tipo da variável de iteração de loop deve ser determinado implicitamente.

Consulte também