C#には、コレクションの操作を簡単に行うことができる 「LINQ」 という機能があります。
今回は、LINQで使用できる様々なメソッドについて、詳しく解説していきたいと思います。
※この記事では記述するC#のバージョンを9.0系に合わせています。
C#のLINQとは?
LINQとは、「Language Integrated Query(言語統合クエリ)」の略で、C#やVBなどの.NET言語で使用可能な機能の1つです。
コレクションやデータベース、XMLといった様々なデータソースでのデータのやりとりを、統一された構文によって操作することができます。
上述したデータ操作は一般的に、foreachなどのループ処理を使用して行うこともできますが、LINQを活用した場合、コードをより簡潔的に記述しやすくなるメリットがあります。
ラムダ式とは?
LINQを使用する際に合わせて活用するのが、ラムダ式と呼ばれる記法です。
ラムダ式とは、デリゲートやメソッドの引数などで匿名関数を定義する際に、通常の構文よりも簡潔に記述できる方法のことを言います。
ラムダ式で関数を定義する際は、以下のように 「ラムダ演算子 (=>) 」 と呼ばれる演算子を使用します。
【基本構文】
(引数)=> 処理内容;
左辺で関数に渡す引数を指定し、右辺に関数の処理内容を記述します。
引数は通常の構文と同様に () で囲って指定しますが、引数が1つのみの場合は省略することが可能です。
【サンプルコード】
// 引数なし
() => 10 + 5;
// 引数あり
(x, y) => x + y;
// 1つの場合は省略可能
x => x + 5;
LINQで使用する主なメソッド一覧
LINQでは様々なメソッドが用意されていますが、その中でもよく使用されるものを紹介します。
- .Select() … コレクション内の要素全てに対して指定の処理をする
- .Where() … 要素を指定した条件で絞り込む
- .OrderBy() … 要素を昇順に並び替える
- .OrderByDescending() … 要素を降順に並び替える
- .Reverse() … 要素を逆順に並び替える
- .Any() … 指定した条件に一つでも合致する要素があるかどうかを判断する
- .All() … 指定した条件に全要素が合致するかどうかを判断する
- .Contains() … 指定した要素が含まれているかを判断する
- .Max() … コレクション内の要素の中から最大値を返す
- .Min() … コレクション内の要素の中から要素の最小値を返す
- .Average() … コレクション内の全要素の平均値を返す
- .Sum() … コレクション内の全要素の合計を返す
- .Count() … コレクションの要素数を返す
- .ToArray() … 配列に変換する
- .ToList() … リストに変換する
いくつかの項目については、以下で詳しい解説も行なっていますので、ぜひ参考にしてみてください。
Selectメソッドの使い方
Selectメソッドは、処理対象とするコレクションの要素全てに同様の処理を行い、その結果を新たなコレクションとして取得することができるメソッドです。
通常、foreachで要素を1つずつ取り出すなどして行う処理を、このメソッドで簡潔に記述することができます。
以下のサンプルコードで動作を確認してみましょう。
【サンプルコード】
using System;
using System.Linq;
namespace MyCompiler {
class Program {
public static void Main(string[] args) {
int[] sampleArray = {1, 2, 3, 4, 5};
var result = sampleArray.Select(x => x + 10);
foreach (var num in result){
Console.WriteLine(num);
}
}
}
}
【実行結果】
11
12
13
14
15
Selectメソッドを使用することによって、配列の要素全てに同様の処理が行われているのが分かりますね。
ループ処理で同様の処理を実装する場合、複数行に渡ってコードを書く必要がありますが、Selectメソッドの場合はこのように一行で処理をまとめることができます。
なお、LINQを使用する場合は冒頭に 「using System.Linq;」 とコードを書く必要があるので、忘れずに記述しておきましょう。
Whereメソッドと組み合わせて使う
特定の条件を満たす要素のみに処理を行いたい場合に活用できるのが、LINQの Whereメソッドです。
Whereメソッドでは、引数に指定した条件式を元に、対象のコレクションの要素をフィルタリングすることができます。
【サンプルコード】
int[] sampleArray = {1, 2, 3, 4, 5};
foreach (var num in sampleArray.Where(num => num % 2 == 0)){
Console.WriteLine(num);
}
【実行結果】
2
4
Selectメソッドなどを使用する際に合わせて活用することで、処理を行う要素を限定することができます。
【サンプルコード】
int[] sampleArray = {1, 2, 3, 4, 5};
var result = sampleArray
.Where(num => num % 2 == 0)
.Select(x => x + 10);
foreach (var num in result){
Console.WriteLine(num);
}
【実行結果】
12
14
SelectManyメソッドの使い方
Selectと似た処理を行うメソッドに、SelectManyというメソッドがあります。
SelectManyメソッドは主に、入れ子状態となっているコレクションに対して使用するメソッドです。
特定のコレション内に入れ子状態で格納されている各コレクションの要素をそれぞれ取り出し、1つのコレクションとしてまとめる(平坦化する)機能を持っています。
文章で理解するのは少し難しいかと思うので、実際の動きを元に、Selectメソッドと SelectManyメソッドの違いを見てみましょう。
【サンプルコード】
var shopList = new[]
{
new {
Name = "A店",
Goods = new[] {
"鉛筆", "消しゴム", "ハサミ"
}
},
new {
Name = "B店",
Goods = new[] {
"コップ", "茶碗", "箸", "フォーク", "スプーン"
}
},
new {
Name = "C店",
Goods = new[] {
"洋服", "帽子", "靴"}
}
};
// Selectメソッド
var allGoods1 = shopList.Select(s => s.Goods);
Console.Write($"Select:{string.Join(", ", allGoods1)}\n");
// SelectManyメソッド
var allGoods2 = shopList.SelectMany(s => s.Goods);
Console.Write($"SelectMany:{string.Join(", ", allGoods2)}\n");
【実行結果】
Select:System.String[], System.String[], System.String[]
SelectMany:鉛筆, 消しゴム, ハサミ, コップ, 茶碗, 箸, フォーク, スプーン, 洋服, 帽子, 靴
結果を見ると分かるように、Selectメソッドの場合は入れ子状態となっているコレクションの状態をそのまま保持しますが、SelectManyメソッドの場合は中の要素を取り出し、1つのコレクションとして平坦化しています。
入れ子状態となっているコレクションを一旦外に取り出してから各要素にアクセスするという2つの工程を、1つの処理で実行することができるのが SelectManyメソッドの特徴です。
GroupByメソッドの使い方
GroupByメソッドは、引数に指定したキーを元に、コレクション内の要素をグループ化するメソッドです。
まずは、以下のサンプルコードで実際の動作を確認してみましょう。
【サンプルコード】
var itemList = new[]
{
new {Category = "筆記用具", Name = "鉛筆"},
new {Category = "食器", Name = "茶碗"},
new {Category = "筆記用具", Name = "消しゴム"},
new {Category = "衣類", Name = "Tシャツ"},
new {Category = "食器", Name = "フォーク"},
};
var group = itemList.GroupBy(i => i.Category);
foreach (var category in group){
Console.Write($"{category.Key}:\n");
foreach (var items in category){
Console.Write($" -{items.Name}\n");
};
};
【実行結果】
筆記用具:
-鉛筆
-消しゴム
食器:
-茶碗
-フォーク
衣類:
-Tシャツ
結果を見ると、各コレクションの Category の値を基準にグループ分けされているのが分かりますね。
このように、GroupByメソッドを使用することで、対象のコレクション内の要素をグループ化することができます。
OrderByメソッドと組み合わせて使う
ケースによっては、コレクション内の要素を昇順、もしくは降順に並び替えたい場合もあるかと思います。
その際に活用できるのが、OrderByメソッドと OrderByDescendingメソッドです。
OrderByメソッドを使用すると、要素を昇順に並び替えることができます。
OrderByDescendingメソッドの場合は、降順に並び替えます。
また、Whereメソッドの時と同様に、他のメソッドと組み合わせて使用することも可能です。
試しに、先ほど解説した GroupByメソッドと組み合わせて、要素を昇順に並べた後にグループ化してみましょう。
【サンプルコード】
var itemList = new[]
{
new {Category = "筆記用具", Price = 200, Name = "鉛筆"},
new {Category = "食器", Price = 700, Name = "茶碗"},
new {Category = "筆記用具", Price = 300, Name = "消しゴム"},
new {Category = "衣類", Price = 1900, Name = "Tシャツ"},
new {Category = "食器", Price = 550, Name = "フォーク"},
new {Category = "食器", Price = 900, Name = "箸"},
new {Category = "筆記用具", Price = 400, Name = "ノート"},
new {Category = "衣類", Price = 3200, Name = "ジーンズ"},
new {Category = "衣類", Price = 1200, Name = "靴下"},
};
var group = itemList
.OrderBy(i => i.Price)
.GroupBy(i => i.Category);
foreach (var category in group){
Console.Write($"{category.Key}\n");
foreach (var items in category){
Console.Write($" -{items.Name}:{items.Price}円\n");
};
};
【実行結果】
筆記用具
-鉛筆:200円
-消しゴム:300円
-ノート:400円
食器
-フォーク:550円
-茶碗:700円
-箸:900円
衣類
-靴下:1200円
-Tシャツ:1900円
-ジーンズ:3200円
OrderByメソッドと GroupByメソッドを組み合わせて使用する際は、先に OrderByメソッドで要素を並べ替えてからグループ化するようにしましょう。
GroupByメソッドを先に使用してしまうと、各グループに対して OrderByメソッドを呼び出す必要が出てしまうため、並び替えをしてからグループ化を行う方がより効率的です。
Count, Max, Sumでデータを集計する
LINQには、集計演算子と呼ばれる集計操作を行うためのメソッドがいくつか用意されています。
主なメソッドは、以下の通りです。
- Max … 最大値を取得
- Min … 最小値を取得
- Average … 平均値を取得
- Sum … 合計値を取得
- Count … 要素数を取得
以下のサンプルコードで、それぞれの動きを見てみましょう。
【サンプルコード】
var numArray = new[] {1, 2, 3, 4, 5};
// 最大値
var maxNum = numArray.Max(x => x);
// 最小値
var minNum = numArray.Min(x => x);
// 平均値
var averageNum = numArray.Average(x => x);
// 合計値
var sumNum = numArray.Sum(x => x);
// 要素数
var countNum = numArray.Count();
Console.Write($"最大値:{maxNum}\n");
Console.Write($"最小値:{minNum}\n");
Console.Write($"平均値:{averageNum}\n");
Console.Write($"合計値:{sumNum}\n");
Console.Write($"要素数:{countNum}\n");
【実行結果】
最大値:5
最小値:1
平均値:3
合計値:15
要素数:5
いずれのメソッドも引数の指定の仕方は同じですが、Countメソッドのみ引数が必要ありません。
Any, Allで要素が条件を満たしているかチェックする
LINQのAnyメソッドやAllメソッドを使用して、指定の条件を満たす要素が存在するかどうかを判定することができます。
それぞれ、確認してみましょう。
Anyで条件を満たす要素が1つでもあるかチェックする
条件を満たす要素が1つ以上存在するかをチェックしたい場合は、Anyメソッドを使用します。
Anyメソッドでは、指定した条件を満たす要素がコレクションに1つでも含まれている場合、Trueを返却します。
以下のサンプルコードで確認してみましょう。
【サンプルコード】
var itemList = new[]
{
new {Category = "筆記用具", Price = 200, Name = "鉛筆"},
new {Category = "食器", Price = 700, Name = "茶碗"},
new {Category = "筆記用具", Price = 300, Name = "消しゴム"},
new {Category = "衣類", Price = 1900, Name = "Tシャツ"},
new {Category = "食器", Price = 550, Name = "フォーク"},
new {Category = "食器", Price = 900, Name = "箸"},
new {Category = "筆記用具", Price = 400, Name = "ノート"},
new {Category = "衣類", Price = 3200, Name = "ジーンズ"},
new {Category = "衣類", Price = 1200, Name = "靴下"},
};
if(itemList.Any(i => i.Price > 1000)) {
Console.WriteLine("1000円を超える商品があります。");
} else {
Console.WriteLine("1000円を超える商品はありません。");
}
【実行結果】
1000円を超える商品があります。
条件指定は省略することも可能で、その場合はコレクション内に要素が含まれるか否かで判断されます。
【サンプルコード】
var sampleArray1 = new int[] {1, 2, 3};
var sampleArray2 = new int[] {};
if(sampleArray1.Any()) {
Console.WriteLine("sampleArray1は要素が含まれています。");
} else {
Console.WriteLine("sampleArray1は要素が含まれていません。");
}
if(sampleArray2.Any()) {
Console.WriteLine("sampleArray2は要素が含まれています。");
} else {
Console.WriteLine("sampleArray2は要素が含まれていません。");
}
【実行結果】
sampleArray1は要素が含まれています。
sampleArray2は要素が含まれていません。
LINQ to XMLで XMLを解析する
C#では、LINQ to XMLという機能を使用して、XMLファイルの操作を行うこともできます。
以下のサンプルコードで動作を確認してみましょう。
【サンプルコード(XML)】
・xml
<?xml version="1.0" encoding="utf-8" ?>
<Student>
<Name>山田 太郎</Name>
<Name>佐藤 花子</Name>
<Name>田中 二郎</Name>
<Name>後藤 由香</Name>
<Name>藤井 光輝</Name>
</Student>
【サンプルコード(C#)】
// xmlファイルのパスを取得
string xmlFilePath = Directory.GetCurrentDirectory() + @“\sample.xml";
// xmlファイルの読み込み
var sampleData = XElement.Load(xmlFilePath);
// 名前を全て取得
var studentName = from student in sampleData.Elements("Student").Elements("Name") select student.Value;
// 取得した名前を出力
foreach (string name in studentName){
Console.WriteLine(name);
}
【実行結果】
山田 太郎
佐藤 花子
田中 二郎
後藤 由香
藤井 光輝
上記のサンプルでは簡単なデータの取得のみを行っていますが、ここまでに紹介したメソッドなどと組み合わせて使用することで、条件を満たすデータのみを取得したりなどいった様々な操作を簡単に行うこともできます。
まとめ
いかがでしたか?
LINQを使いこなせるようにしておくと、複雑な処理も簡潔にまとめることができ、非常に便利です。
ぜひ、活用してみてくださいね。
C#の勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、C#に限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!

ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。