共用方式為


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

Language-Integrated Query (LINQ) 查詢作業會使用彼此相容的強型別變數。 查詢本身與查詢執行都會使用強型別的資料來源。 下圖是用以描述 LINQ 查詢的詞彙。 如需查詢各部分的詳細資訊,請參閱 基本查詢作業 (Visual Basic)

Screenshot showing a pseudocode query with elements highlighted.

查詢中範圍變數的類型,必須與資料來源中元素的類型相容。 查詢變數的類型必須與 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 陳述式會傳回每個 Customer 物件的 Name 屬性,而不會傳回整個物件。 因為 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

需要匿名類型的查詢

下列範例顯示更複雜的狀況。 在上述範例中,要明確指定所有變數的類型,很不方便。 在此範例中更是不可能。 此查詢中的 Select 子句不會選取資料來源中所有的 Customer 元素,或是每個元素中的某個欄位,而會傳回原始 Customer 物件的 NameCity 屬性。 編譯器定義了包含這兩項屬性的匿名型別來回應 Select 子句。 在 For Each 迴圈中執行 nameCityQuery,會得到新匿名型別執行個體集合的結果。 因為匿名型別沒有名稱可用,所以您無法明確指定類型 nameCityQuerycustInfo。 亦即,使用匿名型別時,您沒有類型名稱可用來取代 IEnumerable(Of String) 中的 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. 資料來源中元素的類型在查詢中仍是範圍變數的類型。 在此範例中,custCustomer 的執行個體。

  2. 因為 Select 陳述式會產生匿名型別,所以查詢變數 nameCityQuery 必須是隱含類型的匿名型別。 因為匿名型別沒有名稱可用,所以您無法明確指定。

  3. For Each 迴圈中的反覆運算變數類型是在步驟 2 中建立的匿名型別。 因為類型沒有名稱可用,所以迴圈反覆運算變數的類型必須間接指定。

另請參閱