Funzionalità di Visual Basic che supportano LINQ

Il nome Language-Integrated Query (LINQ) fa riferimento alla tecnologia in Visual Basic che supporta la sintassi di query e altri costrutti di linguaggio direttamente nel linguaggio. Con LINQ non è necessario apprendere un nuovo linguaggio per eseguire query su un'origine dati esterna. È possibile eseguire query sui dati in database relazionali, archivi XML o oggetti tramite Visual Basic. Questa integrazione delle funzionalità di query nel linguaggio consente il controllo in fase di compilazione per gli errori di sintassi e la sicurezza dei tipi. Questa integrazione garantisce inoltre di conoscere già la maggior parte di ciò che è necessario sapere per scrivere query avanzate e diverse in Visual Basic.

Le sezioni seguenti descrivono i costrutti di linguaggio che supportano LINQ in modo sufficientemente dettagliato per iniziare a leggere la documentazione introduttiva, gli esempi di codice e le applicazioni di esempio. È anche possibile fare clic sui collegamenti per trovare spiegazioni più dettagliate sul modo in cui le funzionalità del linguaggio vengono unite per abilitare la query integrata nel linguaggio. Un buon punto di partenza è Procedura dettagliata: scrittura di query in Visual Basic.

Espressioni di query

Le espressioni di query in Visual Basic possono essere espresse in una sintassi dichiarativa simile a quella di SQL o XQuery. In fase di compilazione la sintassi della query viene convertita nelle chiamate al metodo per l'implementazione di un provider LINQ dei metodi di estensione degli operatori di query standard. Le applicazioni controllano gli operatori di query standard nell'ambito specificando lo spazio dei nomi appropriato con un'istruzione Imports. La sintassi per un'espressione di query di Visual Basic è simile alla seguente:

Dim londonCusts = From cust In customers
                  Where cust.City = "London"
                  Order By cust.Name Ascending
                  Select cust.Name, cust.Phone

Per altre informazioni, vedere Introduzione a LINQ in Visual Basic.

Variabili tipizzate in modo implicito

Anziché specificare in modo esplicito un tipo quando si dichiara e inizializza una variabile, è possibile consentire al compilatore di dedurre e assegnare il tipo. Questa operazione viene definita inferenza del tipo locale.

Le variabili i cui tipi sono dedotti sono fortemente tipizzati, proprio come le variabili di cui si specifica il tipo specificato in modo esplicito. L'inferenza del tipo locale funziona solo quando si definisce una variabile locale all'interno di un corpo del metodo. Per altre informazioni, vedere Istruzione di inferenza di opzioni e Inferenza del tipo locale.

Nell'esempio seguente viene illustrata l'inferenza del tipo locale. Per usare questo esempio, è necessario impostare Option Infer su On.

' The variable aNumber will be typed as an integer.
Dim aNumber = 5

' The variable aName will be typed as a String.
Dim aName = "Virginia"

L'inferenza del tipo locale consente anche di creare tipi anonimi, descritti più avanti in questa sezione e necessari per le query LINQ.

Nell'esempio LINQ seguente l'inferenza del tipo si verifica se Option Infer è On o Off. Si verifica un errore in fase di compilazione se Option Infer è Off e Option Strict è On.

' Query example.
' If numbers is a one-dimensional array of integers, num will be typed
' as an integer and numQuery will be typed as IEnumerable(Of Integer)--
' basically a collection of integers.

Dim numQuery = From num In numbers
               Where num Mod 2 = 0
               Select num

Inizializzatori di oggetti

Gli inizializzatori di oggetti vengono usati nelle espressioni di query quando è necessario creare un tipo anonimo per contenere i risultati di una query. Possono anche essere usati per inizializzare oggetti di tipi denominati all'esterno delle query. Usando un inizializzatore di oggetto, è possibile inizializzare un oggetto in una singola riga senza chiamare in modo esplicito un costruttore. Supponendo di avere una classe denominata Customer con proprietà Name e Phone pubbliche, insieme ad altre proprietà, è possibile usare un inizializzatore di oggetto in questo modo:

Dim aCust = New Customer With {.Name = "Mike",
                               .Phone = "555-0212"}

Per altre informazioni, vedere Inizializzatori di oggetti: tipi denominati e anonimi.

Tipi anonimi

I tipi anonimi consentono di raggruppare temporaneamente un set di proprietà in un elemento da includere in un risultato della query. In questo modo è possibile scegliere qualsiasi combinazione di campi disponibili nella query, in qualsiasi ordine, senza definire un tipo di dati denominato per l'elemento.

Un tipo anonimo viene costruito dinamicamente dal compilatore. Il nome del tipo viene assegnato dal compilatore e può cambiare con ogni nuova compilazione. Pertanto, il nome non può essere utilizzato direttamente. I tipi anonimi vengono inizializzati nel modo seguente:

' Outside a query.
Dim product = New With {.Name = "paperclips", .Price = 1.29}

' Inside a query.
' You can use the existing member names of the selected fields, as was
' shown previously in the Query Expressions section of this topic.
Dim londonCusts1 = From cust In customers
                   Where cust.City = "London"
                   Select cust.Name, cust.Phone

' Or you can specify new names for the selected fields.
Dim londonCusts2 = From cust In customers
                   Where cust.City = "London"
                   Select CustomerName = cust.Name,
                   CustomerPhone = cust.Phone

Per altre informazioni, vedere Tipi anonimi.

Metodi di estensione

I metodi di estensione consentono di aggiungere metodi a un tipo di dati o a un'interfaccia dall'esterno della definizione. Questa funzionalità consente, in effetti, di aggiungere nuovi metodi a un tipo esistente senza modificare effettivamente il tipo. Gli operatori query standard sono essi stessi un set di metodi di estensione che forniscono funzionalità di query LINQ per qualsiasi tipo che implementa IEnumerable<T>. Altre estensioni per IEnumerable<T> includono Count, Union e Intersect.

Il metodo di estensione seguente aggiunge un metodo print alla classe String.

' Import System.Runtime.CompilerServices to use the Extension attribute.
<Extension()>
Public Sub Print(ByVal str As String)
    Console.WriteLine(str)
End Sub

Il metodo viene chiamato come un metodo di istanza comune di String:

Dim greeting As String = "Hello"
greeting.Print()

Per altre informazioni, vedere Metodi di estensione.

Espressioni lambda

Un'espressione lambda è una funzione senza un nome che calcola e restituisce un singolo valore. A differenza delle funzioni denominate, è possibile definire ed eseguire contemporaneamente un'espressione lambda. Nell'esempio seguente viene visualizzato 4.

Console.WriteLine((Function(num As Integer) num + 1)(3))

È possibile assegnare la definizione dell'espressione lambda a un nome di variabile e quindi usare il nome per chiamare la funzione. Nell'esempio seguente viene visualizzato anche 4.

Dim add1 = Function(num As Integer) num + 1
Console.WriteLine(add1(3))

In LINQ le espressioni lambda sono alla base di molti degli operatori di query standard. Il compilatore crea espressioni lambda per acquisire i calcoli definiti nei metodi di query fondamentali, ad esempio Where, Select, Order By, Take While e altri.

Ad esempio, il codice seguente definisce una query che restituisce tutti gli studenti senior da un elenco di studenti.

Dim seniorsQuery = From stdnt In students
                   Where stdnt.Year = "Senior"
                   Select stdnt

La definizione della query viene compilata in codice simile all'esempio seguente, che usa due espressioni lambda per specificare gli argomenti per Where e Select.

Dim seniorsQuery2 = students.
    Where(Function(st) st.Year = "Senior").
    Select(Function(s) s)

È possibile eseguire una delle due versioni usando un ciclo For Each:

For Each senior In seniorsQuery
    Console.WriteLine(senior.Last & ", " & senior.First)
Next

Per altre informazioni, vedere Espressioni lambda.

Vedi anche