支援 LINQ 的 Visual Basic 功能

Language-Integrated Query (LINQ) 這個名稱指的是 Visual Basic 中的技術,其可直接在語言中支援查詢語法和其他語言建構。 有了 LINQ,您就不需要為了查詢外部資料來源而去學習新語言。 您可以使用 Visual Basic 來對關聯式資料庫、XML 存放區或物件中的資料進行查詢。 語言與查詢功能的這項整合,能讓您針對語法錯誤和類型安全進行編譯時間檢查。 這項整合也能確保您已經知道在 Visual Basic 中撰寫豐富又多樣的查詢時所需要的大多數條件。

下列各節將詳細說明支援 LINQ 的語言建構,讓您開始閱讀簡介文件、程式碼範例和應用程式範例。 您也可以按一下連結來找到更詳細的說明,以了解語言功能如何相結合來實現語言整合式查詢。 建議從逐步解說:在 Visual Basic 中撰寫查詢開始。

查詢運算式

就和 SQL 或 XQuery 一樣,Visual Basic 中的查詢運算式可用宣告式語法來表示。 在編譯時間,查詢語法會轉換成對 LINQ 提供者實作的標準查詢運算子擴充方法進行的方法呼叫。 應用程式使用 Imports 陳述式來指定適當的命名空間,藉此控制範圍內的標準查詢運算子。 Visual Basic 查詢運算式的語法如下所示:

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

如需詳細資訊,請參閱 Visual Basic 中的 LINQ 簡介

隱含類型變數

除了在宣告和初始化變數時明確指定類型,您還可以讓編譯器推斷並指派類型。 這稱為「區域型別推斷」

推斷類型為強型別的變數,就像明確指定類型的變數一樣。 只有當您在方法主體內定義區域變數時,區域型別推斷才能運作。 如需詳細資訊,請參閱 Option Infer 陳述式區域型別推斷

下列範例說明區域型別推斷。 若要使用此範例,您必須將 Option Infer 設定為 On

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

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

區域型別推斷也能讓您建立匿名型別,這會在本節稍後說明,且為 LINQ 查詢的必要項目。

下列 LINQ 範例中,如果 Option InferOnOff,就會發生型別推斷。 如果 Option InferOffOption StrictOn,就會發生編譯時期錯誤。

' 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

物件初始設定式

當您必須建立匿名型別來保留查詢結果時,會在查詢運算式中使用物件初始設定式。 它們也可以用來初始化查詢外部具名型別的物件。 您可以使用物件初始設定式,在不明確呼叫建構函式的情況下將單一行中的物件初始化。 假設您有類別稱為 Customer 且其有公用的 NamePhone 屬性與其他屬性,則可以透過以下方式使用物件初始設定式:

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

如需詳細資訊,請參閱物件初始設定式:具名和匿名型別

匿名類型

匿名型別提供便利的方式來暫時將一組屬性分組到您想包含在查詢結果內的元素。 這讓您不必為元素定義具名資料類型,就能以任意順序在查詢中選擇任意組合的可用欄位。

「匿名型別」是由編譯器以動態方式建構。 編譯器會指派類型的名稱,而且可能會隨著每個新的編譯而變更。 因此,無法直接使用名稱。 匿名型別會以下列方式初始化:

' 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

如需詳細資訊,請參閱匿名型別

擴充方法

擴充方法可讓您從定義外部將方法新增至資料類型或介面。 這項功能實際上可讓您新增方法至現有的類型,而不需要實際修改類型。 標準查詢運算子本身是一組擴充方法,可為實作 IEnumerable<T> 的任何類型提供 LINQ 查詢功能。 IEnumerable<T> 的其他延伸模組包含 CountUnionIntersect

下列擴充方法會將列印方法新增至 String 類別。

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

方法的呼叫方式就如同 String 的一般執行個體方法:

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

如需詳細資訊,請參閱擴充方法

Lambda 運算式

Lambda 運算式是沒有名稱的函式,可計算並傳回單一值。 不同於具名函式,Lambda 運算式可以同時定義和執行。 下列範例顯示 4。

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

您可以將 Lambda 運算式定義指派給變數名稱,然後使用名稱來呼叫函式。 下列範例也顯示 4。

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

在 LINQ 中,Lambda 運算式是許多標準查詢運算子的基礎。 編譯器會建立 Lambda 運算式來擷取在 WhereSelectOrder ByTake While 等其他基本查詢方法中定義的計算。

舉例來說,以下程式碼會定義查詢,該查詢會從學生清單中傳回所有資深學生。

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

查詢定義會編譯到程式碼中,如以下範例所示,其使用兩個 Lambda 運算式來為 WhereSelect 指定引數。

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

任一版本都能藉由使用 For Each 迴圈來執行:

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

如需詳細資訊,請參閱 Lambda 運算式

另請參閱