Language-Integrated Query (LINQ)查詢作業中使用的變數是強類型,而且必須互相相容。 強型別用於數據源、查詢本身和查詢執行中。 下圖識別用來描述LINQ查詢的詞彙。 如需查詢部分的詳細資訊,請參閱基本查詢作業(Visual Basic)。
查詢中範圍變數的類型必須與數據源中的項目類型相容。 查詢變數的類型必須與 Select 子句中定義的序列元素相容。 最後,序列元素的類型也必須與執行查詢之 For Each 語句中使用的迴圈控件變數類型相容。 強型別檢查促使在編譯時期識別類型錯誤。
Visual Basic 藉由實作類型推斷,也稱為隱含類型,讓強類型變得方便。 此功能會在上一個範例中使用,而且您會在 LINQ 範例和檔中看到此功能使用。 在 Visual Basic 中,本機類型推斷只需透過使用不含 Dim 子句的 As 語句即可完成。 在下列範例中,city 被強型別定義為字串。
Dim city = "Seattle"
備註
本機類型推斷只有在 Option Infer 設定為 On 時才有效。 如需詳細資訊,請參閱 Option Infer 語句。
不過,即使您在查詢中使用本機類型推斷,數據源中的變數、查詢變數和查詢執行迴圈中也會有相同的類型關聯性。 當您撰寫 LINQ 查詢或處理檔中的範例和程式代碼範例時,對於這些類型關聯性有基本的瞭解會很有用。
您可能需要為不符合數據來源所傳回之型別的範圍變數指定明確的類型。 您可以使用 子句來指定範圍變數 As 的類型。 不過,如果轉換是 縮小轉換 且 Option Strict 設定 On為 ,則會產生錯誤。 因此,建議您對從數據源擷取的值執行轉換。 您可以使用 方法,將數據源中的值轉換成明確的範圍變數類型 Cast 。 您也可以將 子句中 Select 選取的值轉換成與範圍變數類型不同的明確類型。 下列程式代碼會說明這些點。
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)
傳回源數據之整個元素的查詢
下列範例顯示 LINQ 查詢作業,此作業會傳回從源數據選取的元素序列。 來源 names包含字串陣列,而查詢輸出是包含以字母 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
這相當於下列程序代碼,但更容易撰寫。 依賴查詢中的本機類型推斷是 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
下列關聯性存在於上述兩個程式代碼範例中,不論類型是隱含還是明確決定。
數據源
names中的元素類型是查詢中範圍變數name的類型。所選取物件的型別,
name會決定查詢變數mNames的類型。 以下是name字串,因此查詢變數在Visual Basic中為IEnumerable(Of String)。在
mNames定義的查詢在For Each迴圈中執行。 迴圈會逐一查看執行查詢的結果。 因為mNames執行時,會傳回一連串字串,迴圈反覆運算變數nm, 也是字串。
從選定元素傳回一個欄位的查詢
下列範例顯示 LINQ to SQL 查詢作業,其會傳回序列,其中只包含從數據源選取的每個元素的一個部分。 查詢會採用 Customer 物件集合 作為其數據源,並僅投影結果中的 Name 屬性。 因為客戶名稱是字串,因此查詢會產生一連串字串做為輸出。
' 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
變數之間的關聯性就像簡單範例中的關聯性一樣。
數據源
customers中的元素類型是查詢中範圍變數cust的類型。 在這裡範例中,該類型為Customer。語句
Select會Name傳回每個Customer物件的 屬性,而不是整個物件。 因為Name是字串,因此查詢變數custNames會再次是 IEnumerable(Of String),而不是Customer。因為
custNames代表字串序列,迴圈For Each的反覆運算變數custName必須是字串。
如果沒有局部類型推斷,之前的範例會變得更繁瑣,不易撰寫和理解,如下列範例所示。
' 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
需要匿名類型的查詢
下列範例顯示更複雜的情況。 在上一個範例中,明確指定所有變數的類型不方便。 在此範例中,不可能。 此查詢中的Customer子句將傳回原始Select物件的兩個屬性:Customer和Name,而不是從數據源選取整個City元素或從每個元素選取單一欄位。 為了回應 Select 子句,編譯程式會定義包含這兩個屬性的匿名型別。 在 nameCityQuery 迴圈中執行For Each的結果是新匿名型別的實例集合。 因為匿名類型沒有可用名稱,所以您無法明確指定nameCityQuery或custInfo的類型。 也就是說,使用匿名類型時,您沒有類型名稱來取代 String 和 IEnumerable(Of String)。 如需詳細資訊,請參閱 匿名型別。
' 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
雖然無法在上一個範例中指定所有變數的類型,但關聯性會維持不變。
在數據源中的元素類型仍然是查詢中範圍變數的類型。 在此範例中,
cust是的Customer實例。Select由於語句會產生匿名型別,因此查詢變數nameCityQuery必須隱含類型為匿名型別。 匿名類型沒有可使用的名稱,因此無法明確指定。迴圈中
For Each反覆專案變數的類型是步驟 2 中建立的匿名類型。 因為類型沒有可使用的名稱,因此必須以隱含方式判斷迴圈反覆運算變數的類型。