Digite relações em operações de consulta (Visual Basic)
As variáveis usadas em operações de consulta LINQ (Language-Integrated Query) 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 de consulta básicas (Visual Basic).
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. Finalmente, o tipo dos elementos de sequência também deve ser compatível com o tipo da variável de controle de loop que é usada na For Each
instrução que executa a consulta. Essa digitação forte facilita a identificação de erros de tipo em tempo de compilação.
O Visual Basic torna a digitação forte conveniente implementando a inferência de tipo local, também conhecida como digitação implícita. Esse recurso é usado no exemplo anterior e você o verá usado em todas as amostras 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"
Nota
A inferência de tipo local funciona somente quando Option Infer
é definida como On
. Para obter mais informações, consulte Option Infer Statement.
No entanto, mesmo se você usar a 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, na variável de consulta e no loop de execução da consulta. É útil ter uma compreensão básica dessas relações de tipo quando você estiver escrevendo consultas LINQ ou trabalhando 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 range usando uma As
cláusula. No entanto, isso resulta em um erro se a conversão for uma conversão de estreitamento e Option Strict
estiver 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 os valores selecionados na Select
cláusula para um tipo explícito que é diferente do tipo da variável de intervalo. Estes 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)
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 confiança na inferência de tipo local em consultas é o estilo preferido 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, quer os tipos sejam determinados implícita ou explicitamente.
O tipo dos elementos na fonte de dados,
names
, é o tipo da variável de intervalo,name
, na consulta.O tipo do objeto selecionado,
name
, determina o tipo da variável de consulta,mNames
. Aquiname
está uma cadeia de caracteres, portanto, a variável de consulta é IEnumerable(Of String) no Visual Basic.A consulta definida em
mNames
é executadaFor Each
no loop. O loop itera sobre o resultado da execução da consulta. ComomNames
, quando é executado, retornará uma sequência de strings, a variável de iteração de loop,nm
, também é uma string.
O exemplo a seguir mostra uma operação de consulta LINQ to SQL que retorna uma sequência contendo apenas uma parte de cada elemento selecionado da 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 como as do exemplo mais simples.
O tipo dos elementos na fonte de dados,
customers
, é o tipo da variável de intervalo,cust
, na consulta. Neste exemplo, esse tipo éCustomer
.A
Select
instrução retorna aName
propriedade de cadaCustomer
objeto em vez do objeto inteiro. ComoName
é uma cadeia de caracteres, a variável de consulta,custNames
, será novamente IEnumerable(Of String), não deCustomer
.Como
custNames
representa uma sequência de cadeias de caracteres, aFor Each
variável de iteração do loop,custName
, 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
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 nome utilizável, não é possível especificar o tipo de nameCityQuery
ou custInfo
explicitamente. Ou seja, com um tipo anônimo, você não tem nenhum nome de tipo para usar no lugar de String
em IEnumerable(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.
O tipo dos elementos na fonte de dados é novamente o tipo da variável de intervalo na consulta. Neste exemplo,
cust
é uma instância deCustomer
.Como a
Select
instrução produz um tipo anônimo, a variável de consulta,nameCityQuery
, deve ser implicitamente digitada como um tipo anônimo. Um tipo anônimo não tem nome utilizável e, portanto, não pode ser especificado explicitamente.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 nome utilizável, o tipo da variável de iteração de loop deve ser determinado implicitamente.
Comentários do .NET
O .NET é um projeto código aberto. Selecione um link para fornecer comentários: