LINQ をサポートする Visual Basic の機能

統合言語クエリ (LINQ) という名前は、クエリ構文などの言語コンストラクトを言語の中で直接サポートする、Visual Basic のテクノロジをいいます。 LINQ を使用すれば、外部のデータ ソースを照会するために新しい言語を習得する必要はありません。 Visual Basic を使用して、リレーショナル データベースや XML ストア、オブジェクトにデータを照会することができます。 このようにクエリの機能を言語に統合することで、構文エラーやタイプ セーフのチェックをコンパイル時に行えるようになります。 また、多くの場合、既にある知識だけで、豊富で多彩なクエリを Visual Basic で記述することができます。

以降の各セクションでは、これから皆さんが入門ドキュメントやコード例、サンプル アプリケーションを読むために最低限必要な知識が身に付くよう、LINQ をサポートする言語コンストラクトについて説明します。 また、リンク先のドキュメントもご覧ください。さまざまな言語機能がどのように組み合わさって統合言語クエリが実現されているかについて詳しく説明されています。 まずは、「チュートリアル: Visual Basic でのクエリの作成」を読むことをお勧めします。

クエリ式

Visual Basic のクエリ式は、SQL や XQuery と同様の宣言型構文で表現することができます。 クエリ構文は、コンパイル時に、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 InferOn に設定する必要があります。

' 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 InferOn または Off の場合に型の推定が行われます。 Option InferOff で、なおかつ Option 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

オブジェクト初期化子

オブジェクト初期化子は、クエリ式の中で、クエリの結果を保持する匿名型を作成する必要があるときに使用します。 また、名前付きの型のオブジェクトをクエリの外側で初期化する際にも使用できます。 オブジェクト初期化子を使用すれば、コンストラクターを明示的に呼び出さなくても、オブジェクトを 1 行で初期化することができます。 Customer という名前のクラスがあるとしましょう。このクラスには、パブリック プロパティである NamePhone のほか、いくつかのプロパティがあります。この場合、オブジェクト初期化子を次のように使用することができます。

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

詳細については、「オブジェクト初期化子: 名前付きの型と匿名型」を参照してください。

匿名型

クエリの結果に含めたい一連のプロパティを 1 つの要素として一時的にグループ化する場合に、匿名型は高い利便性を発揮します。 その要素に対して名前付きのデータ型を定義しなくても、選択可能なフィールドの組み合わせをクエリの中で自由に、かつ任意の順序で選ぶことができます。

"匿名型" は、コンパイラによって動的に構築されます。 型の名前はコンパイラによって割り当てられ、また、コンパイルのたびに変わる可能性があります。 したがって、その名前を直接使用することはできません。 匿名型の初期化方法は次のとおりです。

' 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 クラスに Print メソッドを追加するものです。

' 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()

詳細については、「拡張メソッド」を参照してください。

ラムダ式

ラムダ式は、単一の値を計算して返す、名前を持たない関数です。 名前付きの関数とは異なり、ラムダ式は、定義と実行を同時に行うことができます。 次の例では、"4" が表示されます。

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

ラムダ式の定義を変数名に代入しておけば、その名前を使用して関数を呼び出すことができます。 次の例でも、"4" が表示されます。

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

LINQ では、ラムダ式が、多くの標準クエリ演算子の基盤となっています。 基本的なクエリ メソッド (WhereSelectOrder ByTake While など) で定義されている計算を取り込むためのラムダ式が、コンパイラによって作成されます。

たとえば、次のコードは、学生のリストからすべての最上級生を返すクエリの定義です。

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

このクエリ定義は、次の例のようなコードにコンパイルされます。このコードでは、2 つのラムダ式を使用して 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

詳細については、「ラムダ式」を参照してください。

関連項目