查詢作業中的類型關聯性 (Visual Basic)

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

下列關聯性存在於上述兩個程式代碼範例中,不論類型是隱含還是明確決定。

  1. 數據源 names 中的元素類型是查詢中範圍變數 name 的類型。

  2. 所選取物件的型別, name會決定查詢變數 mNames的類型。 以下是 name 字串,因此查詢變數在Visual Basic中為IEnumerable(Of String)。

  3. 在 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

變數之間的關聯性就像簡單範例中的關聯性一樣。

  1. 數據源 customers 中的元素類型是查詢中範圍變數 cust 的類型。 在這裡範例中,該類型為 Customer。

  2. 語句 Select 會 Name 傳回每個 Customer 物件的 屬性,而不是整個物件。 因為 Name 是字串,因此查詢變數custNames會再次是 IEnumerable(Of String),而不是 Customer。

  3. 因為 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

雖然無法在上一個範例中指定所有變數的類型,但關聯性會維持不變。

  1. 在數據源中的元素類型仍然是查詢中範圍變數的類型。 在此範例中, cust 是的 Customer實例。

  2. Select由於語句會產生匿名型別,因此查詢變數nameCityQuery必須隱含類型為匿名型別。 匿名類型沒有可使用的名稱,因此無法明確指定。

  3. 迴圈中 For Each 反覆專案變數的類型是步驟 2 中建立的匿名類型。 因為類型沒有可使用的名稱,因此必須以隱含方式判斷迴圈反覆運算變數的類型。

另請參閱