Typbeziehungen in Abfrageoperationen (Visual Basic)
In Sprachintegrierte Abfrage (Language-Integrated Query, LINQ)-Abfrageoperationen verwendete Variablen sind stark typisiert und müssen miteinander kompatibel sein.Die starke Typisierung wird in der Datenquelle, in der Abfrage selbst und in der Abfrageausführung verwendet.Die folgende Abbildung veranschaulicht Begriffe, die zum Beschreiben einer LINQ-Abfrage verwendet werden.Weitere Informationen über die Teile einer Abfrage finden Sie unter Grundlegende Abfrageoperationen (Visual Basic).
Teile einer LINQ-Abfrage
Der Typ der Bereichsvariablen in der Abfrage muss kompatibel mit dem Typ der Elemente in der Datenquelle sein.Der Typ der Abfragevariablen muss kompatibel mit dem Sequenzelement sein, das in der Select-Klausel definiert ist.Schließlich muss der Typ der Sequenzelemente auch kompatibel mit dem Typ der Schleifensteuerungsvariablen sein, die in der For Each-Anweisung zur Ausführung der Abfrage verwendet wird.Diese starke Typisierung erleichtert zur Kompilierzeit die Identifikation von Typfehlern.
Visual Basic erleichtert eine starke Typisierung, indem lokale Typrückschlusse, auch bekannt als implizite Typisierung, implementiert werden.Dieses Feature wird im vorigen Beispiel sowie in allen LINQ-Beispielen und -Dokumentation verwendet.In Visual Basic werden lokale Typrückschlüsse auf einfache Weise durch Verwendung einer Dim-Anweisung ohne As-Klausel erzielt.Im folgenden Beispiel ist city als Zeichenfolge stark typisiert.
Dim city = "Seattle"
Hinweis |
---|
Der lokale Typrückschluss funktioniert nur, wenn Option Infer auf On festgelegt ist.Weitere Informationen finden Sie unter Option Infer-Anweisung. |
Verwenden Sie jedoch einen lokalen Typrückschluss in einer Abfrage, sind die gleichen Typbeziehungen innerhalb der Variablen in der Datenquelle, der Abfragevariablen und der Abfrageausführungsschleife vorhanden.Es ist hilfreich, über ein grundlegendes Verständnis dieser Typbeziehungen zu verfügen, wenn Sie LINQ-Abfragen erstellen oder mit den Beispielen und Codebeispielen in der Dokumentation arbeiten.
Sie müssen möglicherweise einen expliziten Typ für eine Bereichsvariable angeben, der nicht mit dem von der Datenquelle zurückgegeben Typ übereinstimmt.Sie können den Typ der Bereichsvariablen mit einer As-Klausel angeben.Dies führt jedoch zu einem Fehler, wenn es sich um eine eingrenzende Konvertierung handelt und Option Strict auf On festgelegt ist.Aus diesem Grund sollten Sie die von der Datenquelle empfangenen Werte konvertieren.Sie können diese Werte mit der Cast<TResult>-Methode in den expliziten Bereichsvariablentyp konvertieren.Sie können die in der Select-Klausel ausgewählten Werte auch in einen expliziten Typ umwandeln, der nicht mit dem Typ der Bereichsvariablen übereinstimmt.Diese Punkte werden im folgenden Code veranschaulicht.
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)
Abfragen, die ganze Elemente der Quelldaten zurückgeben
Im folgenden Beispiel wird eine LINQ-Abfrageoperation gezeigt, die eine Sequenz von Elementen zurückgibt, die aus den Quelldaten ausgewählt wurden.Die Quelle names enthält ein Zeichenfolgenarray, und die Abfrageausgabe ist eine Sequenz mit Zeichenfolgen, die mit dem Buchstaben M beginnen.
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
Dies ist zu folgendem Code äquivalent, aber viel kürzer und leichter zu schreiben.In Visual Basic wird bevorzugt auf lokale Typrückschlüsse in Abfragen zurückgegriffen.
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
Folgende Beziehungen sind in beiden der vorherigen Codebeispiele vorhanden, ganz gleich, ob die Typen implizit oder explizit ermittelt werden.
Der Typ der Elemente in der Datenquelle names ist der Typ der Bereichsvariablen name in der Abfrage.
Der Typ des Objekts, das ausgewählt ist (name), bestimmt den Typ der Abfragevariablen mNames.Hier ist name eine Zeichenfolge, deshalb ist die Abfragevariable in Visual Basic IEnumerable(Of String).
Die in mNames definierte Abfrage wird in der For Each-Schleife ausgeführt.Die Schleife durchläuft das Ergebnis der Abfrage.Da mNames beim Ausführen eine Zeichenfolgensequenz zurückgibt, ist die Schleifeniterationsvariable nm auch eine Zeichenfolge.
Abfragen, die ein Feld aus ausgewählten Elementen zurückgeben
Im folgenden Beispiel wird eine LINQ to SQL-Abfrageoperation gezeigt, die eine Sequenz zurückgibt, die nur ein Teil jedes in der Datenquelle ausgewählten Elements enthält.Die Abfrage verwendet eine Auflistung von Customer-Objekten als Datenquelle und projiziert nur die Name-Eigenschaft im Ergebnis.Da der Kundenname eine Zeichenfolge ist, erzeugt die Abfrage eine Zeichenfolgensequenz als Ausgabe.
' 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
Die Beziehungen zwischen Variablen gleichen denen im einfacheren Beispiel.
Der Typ der Elemente in der Datenquelle, customers, ist der Typ der Bereichsvariablen, cust, in der Abfrage.In diesem Beispiel ist dieser Typ Customer.
Die Select-Anweisung gibt die Name-Eigenschaft jedes Customer-Objekts statt des vollständigen Objekts zurück.Da Name eine Zeichenfolge ist, ist die Abfragevariable custNames erneut IEnumerable(Of String), und nicht Customer.
Da custNames eine Zeichenfolgensequenz darstellt, muss die Iterationsvariable der For Each-Schleife custName eine Zeichenfolge sein.
Ohne lokale Typrückschlüsse wäre das vorige Beispiel schwieriger zu schreiben und zu verstehen, wie das folgende Beispiel zeigt.
' 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
Abfragen, die anonyme Typen erfordern
Im folgenden Beispiel wird eine komplexere Situation veranschaulicht.Im vorherigen Beispiel war es nicht günstig, Typen für alle Variablen explizit anzugeben.In diesem Beispiel ist es unmöglich.Anstatt ganze Customer-Elemente aus der Datenquelle oder ein einzelnes Feld aus jedem Element auszuwählen, gibt die Select-Klausel in dieser Abfrage zwei Eigenschaften des ursprünglichen Customer-Objekts zurück: Name und City.Als Reaktion auf die Select-Klausel definiert der Compiler einen anonymen Typ, der diese beiden Eigenschaften enthält.Das Ergebnis der Ausführung von nameCityQuery in der For Each-Schleife ist eine Auflistung von Instanzen des neuen anonymen Typs.Da der anonyme Typ keinen verwendbaren Namen hat, können Sie den Typ von nameCityQuery oder custInfo nicht explizit angeben.Das heißt, dass Sie mit einem anonymen Typ keinen Typnamen haben, den Sie anstatt von String in IEnumerable(Of String) verwenden können.Weitere Informationen finden Sie unter Anonyme Typen (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
Obwohl es nicht möglich ist, Typen für alle Variablen im vorigen Beispiel anzugeben, bleiben die Beziehungen gleich.
Der Typ der Elemente in der Datenquelle entspricht auch hier dem Typ der Bereichsvariablen in der Abfrage.In diesem Beispiel ist cust eine Instanz von Customer.
Da die Select-Anweisung einen anonymen Typ erzeugt, muss die Abfragevariable nameCityQuery implizit als anonymer Typ typisiert werden.Ein anonymer Typ hat keinen verwendbaren Namen und kann deshalb nicht explizit angegeben werden.
Der Typ der Iterationsvariablen in der For Each-Schleife ist der in Schritt 2 erstellte anonyme Typ.Da der Typ keinen verwendbaren Namen aufweist, muss der Typ der Schleifeniterationsvariable implizit bestimmt werden.
Siehe auch
Konzepte
Lokaler Typrückschluss (Visual Basic)
Einführung in LINQ in Visual Basic