今回は、VB.NETでのLINQの使い方と具体例をご紹介します。
LINQ(Language Integrated Query)は、VB.NETにおいて配列やリスト、データベースやXMLなど、多様なデータソースに対して統一的なクエリ操作を可能にする機能です。
SQLに似た記述ができるため、データ操作の可読性や保守性を大きく向上させられる点が特長です。
LINQとは
LINQを使うと、コード内でデータを効率よく抽出・並び替え・集計などが行えます。
クエリを書くだけで、実際のデータ構造にかかわらず同じように操作できるため、開発効率を高めるメリットがあります。
また、クエリは実行されるタイミング(遅延実行)をコントロールしやすく、必要な時だけ評価される仕組みも魅力です。
基本構文
LINQには大きく分けてクエリ構文とメソッド構文の2種類があります。
クエリ構文はFrom~Where~Selectなど、SQLによく似た流れでデータに対する操作を記述します。
一方、メソッド構文はWhereやSelect、OrderByなどの拡張メソッドとラムダ式を用いてメソッドチェーン形式で記述します。
どちらを使うかは好みによりますが、プロジェクトやチームのコーディング規約に合わせることが多いです。
実用的な具体例
ここでは、LINQを活用したいくつかのコード例をご紹介します。
それぞれの例で、クエリ構文をどのように記述し、どのような結果を得られるかを確認してみてください。
配列から偶数を抽出する
まずはシンプルな例として、整数配列の中から偶数だけを取り出すコードです。
1 2 3 4 5 6 7 8 9 10 11 12 |
' 偶数を抽出するための配列 Dim numbers As Integer() = {1, 2, 3, 4, 5} ' クエリ構文で偶数を抽出 Dim evenNumbers = From num In numbers Where num Mod 2 = 0 Select num ' 抽出した要素を出力 For Each n In evenNumbers Console.WriteLine(n) Next |
2
4
同じ処理をメソッド構文で書くことも可能です。
1 2 3 4 5 6 |
' メソッド構文で偶数を抽出 Dim evenNumbersMethod = numbers.Where(Function(num) num Mod 2 = 0) For Each n In evenNumbersMethod Console.WriteLine(n) Next |
2
4
並び替えとフィルタリング
次に、リストの中から特定の条件に合う要素を取り出し、その後アルファベット順に並び替える例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
' 文字列リストを用意 Dim names As List(Of String) = New List(Of String) From {"Charlie", "Alice", "Bob", "David", "Anna"} ' "A"で始まる名前を抽出し、アルファベット順に並べ替え Dim sortedNames = From name In names Where name.StartsWith("A") Order By name Select name ' 結果を出力 For Each n In sortedNames Console.WriteLine(n) Next |
Alice
Anna
グループ化と集計
単語のリストを先頭文字ごとにグループ化し、それぞれのグループ内にいくつ単語があるかを集計する例です。
1 2 3 4 5 6 7 8 9 10 |
' 先頭文字ごとにグループ化し、単語の件数を集計 Dim words As List(Of String) = New List(Of String) From {"apple", "apricot", "banana", "blueberry", "avocado"} Dim groupedWords = From word In words Group word By firstChar = word(0) Into Group Select firstChar, Count = Group.Count() For Each item In groupedWords Console.WriteLine($"{item.firstChar}: {item.Count}") Next |
a: 3
b: 2
複数コレクションの結合(Join)
LINQではJoin句を使って、複数のコレクションを特定のキーで結合できます。
以下の例では学生リストと得点リストを学生IDで紐づけ、名前とスコアをまとめて取得しています。
1 2 3 4 5 6 7 8 9 10 11 |
' 学生情報を管理するクラス Public Class Student Public Property ID As Integer Public Property Name As String End Class ' 得点情報を管理するクラス Public Class Score Public Property StudentID As Integer Public Property Score As Integer End Class |
上記クラスを定義したうえで、次のコードを実行してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
' 学生のリストを用意 Dim students As New List(Of Student) From { New Student With {.ID = 1, .Name = "John"}, New Student With {.ID = 2, .Name = "Alice"}, New Student With {.ID = 3, .Name = "Bob"} } ' 得点のリストを用意 Dim scores As New List(Of Score) From { New Score With {.StudentID = 1, .Score = 90}, New Score With {.StudentID = 2, .Score = 85}, New Score With {.StudentID = 3, .Score = 95} } ' Join句で学生リストと得点リストを結合 Dim studentScores = From student In students Join score In scores On student.ID Equals score.StudentID Select student.Name, score.Score ' 結合結果を出力 For Each item In studentScores Console.WriteLine($"{item.Name}: {item.Score}") Next |
John: 90
Alice: 85
Bob: 95
注意点
LINQの実行タイミングは遅延実行が基本のため、データソースが変更されると結果が変わる可能性があります。
そのため、必要に応じて.ToList()などを使って即時実行させることで、不意のデータ変更を防ぐ方法も検討しましょう。
また、複雑なクエリや大規模データの操作ではパフォーマンスへの影響を考慮し、生成されるSQL(LINQ to SQLやEntity Framework利用時)を把握することも重要です。
さらに、遅延実行の性質上、クエリ結果の参照時に例外が発生する場合がありますので、適切にTry-Catchを用いた例外処理を行うと安心です。
デバッグ時には中間結果を変数に格納するなどの工夫が必要になります。
まとめ
VB.NETでのLINQは、コードの可読性と開発効率を向上させる便利な仕組みです。
クエリ構文とメソッド構文を使い分けて、データソースを問わず柔軟に操作できます。
実際のプロジェクトで必要な性能や可読性を考慮しながら、最適な使い方を探ってみてください。