Visual Basic-Features, die LINQ unterstützen

Der Name LINQ (Language Integrated Query) bezieht sich auf eine Technologie in Visual Basic, die Abfragesyntax und andere Sprachkonstrukte direkt in der Programmiersprache unterstützt. Mit LINQ müssen Sie keine neue Sprache erlernen, um externe Datenquellen abzufragen. Sie können Daten in relationalen Datenbanken, XML-Speichern oder Objekten mithilfe von Visual Basic abfragen. Diese Integration von Abfragefunktionen in die Programmiersprache ermöglicht zur Kompilierzeit die Überprüfung auf Syntaxfehler und Typsicherheit. Außerdem wird durch diese Integration sichergestellt, dass Sie bereits über das erforderliche Wissen verfügen, das Sie benötigen, um verschiedenste umfangreiche Abfragen in Visual Basic zu schreiben.

In den folgenden Abschnitten werden die Sprachkonstrukte, die LINQ unterstützen, so ausführlich beschrieben, dass Sie mit dem Lesen der einführenden Dokumentation, Codebeispiele und Beispielanwendungen beginnen können. Über die Links stehen Ihnen ausführlichere Erläuterungen darüber zur Verfügung, wie die Sprachfeatures zusammenarbeiten, um LINQ (Language Integrated Query) zu ermöglichen. Einen guten Ausgangspunkt bietet die exemplarische Vorgehensweise: Schreiben von Abfragen in Visual Basic.

Abfrageausdrücke

Abfrageausdrücke in Visual Basic können in einer deklarativen Syntax ähnlich der von SQL oder XQuery geschrieben werden. Zur Kompilierzeit wird die Abfragesyntax in Methodenaufrufe an eine Implementierung des LINQ-Anbieters der Erweiterungsmethoden des Standardabfrageoperators kompiliert. Anwendungen steuern, welche Standardabfrageoperatoren gültig sind, indem sie den entsprechenden Namespace mit einer Imports-Anweisung angeben. Die Syntax für einen Visual Basic-Abfrageausdruck sieht wie folgt aus:

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

Weitere Informationen finden Sie unter Einführung in LINQ in Visual Basic.

Implizit typisierte Variablen

Anstatt beim Deklarieren und Initialisieren einer Variable einen Typ explizit anzugeben, können Sie den Compiler anweisen, den Typ abzuleiten und zuzuweisen. Dies wird als lokaler Typrückschluss bezeichnet.

Variablen, deren Typen abgeleitet werden, sind stark typisiert, genau wie Variablen, deren Typ Sie explizit angeben. Lokale Typrückschlüsse funktionieren nur, wenn Sie eine lokale Variable innerhalb eines Methodenkörpers definieren. Weitere Informationen finden Sie unter Option Infer-Anweisung und Lokaler Typrückschluss.

Im folgenden Beispiel wird der lokale Typrückschluss veranschaulicht. Um dieses Beispiel zu verwenden, müssen Sie Option Infer auf On festlegen.

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

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

Lokale Typrückschlüsse ermöglichen auch, anonyme Typen zu erstellen, die weiter unten in diesem Abschnitt beschrieben werden und für LINQ-Abfragen erforderlich sind.

Im folgenden LINQ-Beispiel tritt ein Typrückschluss auf, wenn Option Infer entweder On oder Off ist. Wenn Option Infer den Wert Off und Option Strict den Wert On hat, tritt ein Kompilierzeitfehler auf.

' 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

Objektinitialisierer

Objektinitialisierer werden in Abfrageausdrücken verwendet, wenn Sie einen anonymen Typ erstellen müssen, um die Ergebnisse einer Abfrage zu speichern. Sie können auch verwendet werden, um Objekte benannter Typen außerhalb von Abfragen zu initialisieren. Mithilfe eines Objektinitialisierers können Sie ein Objekt auf einer einzelnen Zeile initialisieren, ohne explizit einen Konstruktor aufzurufen. Davon ausgehend, dass Sie über eine Klasse mit dem Namen Customer verfügen, die über die öffentlichen Eigenschaften Name und Phone verfügt, kann ein Objektinitialisierer wie folgt verwendet werden:

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

Weitere Informationen finden Sie unter Objektinitialisierer: Benannte und anonyme Typen.

Anonyme Typen

Anonyme Typen bieten eine bequeme Möglichkeit, mehrere Eigenschaften vorübergehend in einem Element zu gruppieren, das Sie in ein Abfrageergebnis einschließen können. Dadurch können Sie in der Abfrage eine beliebige Kombination von verfügbaren Feldern in beliebiger Reihenfolge auswählen, ohne einen benannten Datentyp für das Element zu definieren.

Anonyme Typen werden vom Compiler dynamisch erstellt. Der Name des Typs wird vom Compiler zugewiesen und kann sich bei jeder neuen Kompilierung ändern. Daher kann der Name nicht direkt verwendet werden. Anonyme Typen werden wie folgt initialisiert:

' 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

Weitere Informationen finden Sie unter Anonyme Typen.

Erweiterungsmethoden

Mit Erweiterungsmethoden können Sie einem Datentyp oder einer Schnittstelle von außerhalb der Definition aus Methoden hinzufügen. Dieses Feature ermöglicht Ihnen, vorhandenen Typen neue Methoden hinzuzufügen, ohne den Typ tatsächlich zu ändern. Die Standardabfrageoperatoren selbst sind eine Reihe von Erweiterungsmethoden, die LINQ-Abfragefunktionen für jeden Typ bieten, der IEnumerable<T> implementiert. Andere Erweiterungen für IEnumerable<T> umfassen Count, Union und Intersect.

Die folgende Erweiterungsmethode fügt der String-Klasse eine print-Methode hinzu.

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

Die Methode wird wie eine gewöhnliche Instanzmethode von String aufgerufen:

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

Weitere Informationen finden Sie unter Erweiterungsmethoden.

Lambda-Ausdrücke

Ein Lambdaausdruck ist eine Funktion ohne Namen, die einen einzelnen Wert berechnet und zurückgibt. Im Gegensatz zu benannten Funktionen können Lambdaausdrücke gleichzeitig definiert und ausgeführt werden. Im folgenden Beispiel wird „4“ angezeigt.

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

Sie können die Definition des Lambdaausdrucks einem Variablennamen zuweisen und diesen Namen dann verwenden, um die Funktion aufzurufen. Im folgenden Beispiel wird ebenfalls „4“ angezeigt.

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

In LINQ liegen Lambdaausdrücke vielen der Standardabfrageoperatoren zugrunde. Der Compiler erstellt Lambdaausdrücke, um die Berechnungen zu erfassen, die in grundlegenden Abfragemethoden wie Where, Select, Order By, Take While und anderen definiert sind.

Der folgende Code definiert z. B. eine Abfrage, die alle Oberstufenschüler*innen aus einer Liste von Schüler*innen zurückgibt.

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

Die Abfragedefinition wird in Code kompiliert, der dem folgenden Beispiel ähnelt und zwei Lambdaausdrücke verwendet, um die Argumente für Where und Select anzugeben.

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

Beide Versionen können mithilfe einer For Each-Schleife ausgeführt werden:

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

Weitere Informationen finden Sie unter Lambdaausdrücke.

Siehe auch