LINQ クエリ式が輝く5つのシーン + α
はじめに
LINQ 便利ですよね 👍 、普段はメソッド式ばかり使用しているので、たまにはクエリ式のことも思い出してあげよう。
ということで、個人的にクエリ式が見やすいと思う使い方をいくつか挙げてみます。

環境
- .NET8
- C#12
クエリ式
var q = from n in numbers
where n % 2 == 0
select n * n;
メソッド式
var m = numbers.Where(n => n % 2 == 0)
.Select(n => n * n);
1.複数配列の結合(内部結合)
複数配列をキー項目で結合する様な場合です。
データ:
var people = new[]
{
new Person { Id = 1, Name = "太郎" },
new Person { Id = 2, Name = "花子" },
new Person { Id = 3, Name = "次郎" }
};
var profiles = new[]
{
new Profile { PersonId = 1, Email = "taro@example.com" },
new Profile { PersonId = 2, Email = "hanako@example.com" },
new Profile { PersonId = 3, Email = "jiro@example.com" }
};
var addresses = new[]
{
new Address { PersonId = 1, City = "東京" },
new Address { PersonId = 2, City = "大阪" },
new Address { PersonId = 3, City = "広島" }
};
クエリ式:
var query =
from p in people
join pr in profiles on p.Id equals pr.PersonId
join a in addresses on p.Id equals a.PersonId
select new { p.Id, p.Name, pr.Email, a.City };
メソッド式:
var query = people
.Join(profiles,
p => p.Id,
pr => pr.PersonId,
(p, pr) => new { p, pr })
.Join(addresses,
pp => pp.p.Id,
a => a.PersonId,
(pp, a) => new { pp.p.Id, pp.p.Name, pp.pr.Email, a.City });
結果:
Id=1, Name=太郎, Email=taro@example.com, City=東京
Id=2, Name=花子, Email=hanako@example.com, City=大阪
Id=3, Name=次郎, Email=jiro@example.com, City=広島
所感:
どうでしょう?個人的には圧倒的にクエリ式の可読性が高いように思います。
メソッド式はパラメータが多い上に、ラムダ式が複数必要なので
何個目に何を渡したら良いのかわからなくなりそうな気がします。
2.複数配列の結合(外部結合)
複数配列をキー項目で結合し、データが存在しなければ空で取得する様な場合です。
データ:
// peopleは1と同じ
var profiles = new[]
{
new Profile { PersonId = 1, Email = "taro@example.com" },
// 2がない
new Profile { PersonId = 3, Email = "jiro@example.com" }
};
var addresses = new[]
{
new Address { PersonId = 1, City = "東京" },
new Address { PersonId = 2, City = "大阪" },
// 3がない
};
クエリ式:
var query =
from p in people
join pr in profiles on p.Id equals pr.PersonId into prg
from pr in prg.DefaultIfEmpty()
join a in addresses on p.Id equals a.PersonId into ag
from a in ag.DefaultIfEmpty()
select new
{
p.Id,
p.Name,
Email = pr?.Email ?? "(なし)",
City = a?.City ?? "(なし)"
};
メソッド式:
var query = people
.GroupJoin(profiles,
p => p.Id,
pr => pr.PersonId,
(p, prg) => new { p, prg })
.SelectMany(tmp => tmp.prg.DefaultIfEmpty(),
(tmp, pr) => new { tmp.p, pr })
.GroupJoin(addresses,
x => x.p.Id,
a => a.PersonId,
(x, ag) => new { x.p, x.pr, ag })
.SelectMany(tmp => tmp.ag.DefaultIfEmpty(),
(tmp, a) => new
{
tmp.p.Id,
tmp.p.Name,
Email = tmp.pr?.Email ?? "(なし)",
City = a?.City ?? "(なし)"
});
結果:
Id=1, Name=太郎, Email=taro@example.com, City=東京
Id=2, Name=花子, Email=(なし), City=大阪
Id=3, Name=次郎, Email=jiro@example.com, City=(なし)
所感:
さらに複雑になった感じ。
私の技術力ではメソッド式は作ることができませんでした。
ChatGPT 先生にお願いして作ってもらいました。
3.中間結果を使用するような場合
途中に計算などが入り let を使う必要があるような場合
データ:
var students = new[]
{
new Student { Name = "Aさん", Math = 80, English = 70, Science = 60 },
new Student { Name = "Bさん", Math = 50, English = 55, Science = 40 },
new Student { Name = "Cさん", Math = 90, English = 85, Science = 95 },
new Student { Name = "Dさん", Math = 60, English = 60, Science = 60 },
};
クエリ式:
var query =
from s in students
let total = s.Math + s.English + s.Science
let average = total / 3.0
where average >= 60.0
select new { s.Name, average };
メソッド式:
var query = students
.Select(s => new { s.Name, total = s.Math + s.English + s.Science })
.Select(x => new { x.Name, average = x.total / 3.0 })
.Where(x => x.average >= 60.0)
.Select(x => new { x.Name, x.average });
結果:
Aさん: 70.0
Cさん: 90.0
Dさん: 60.0
所感:
メソッド式は中間結果を匿名型や Tuple などで保持することになります。
計算結果を let で保持しておく事ができるクエリ式が有利?
4.複数項目の並び替えがある場合
データ:
var people = new Person[]
{
new Person { Name = "Aさん", Age = 30, Income = 500, Department = "Sales", YearsAtCompany = 5 },
new Person { Name = "Bさん", Age = 25, Income = 450, Department = "Dev", YearsAtCompany = 2 },
new Person { Name = "Cさん", Age = 30, Income = 480, Department = "Dev", YearsAtCompany = 4 },
new Person { Name = "Dさん", Age = 25, Income = 520, Department = "Sales", YearsAtCompany = 3 },
new Person { Name = "Eさん", Age = 40, Income = 600, Department = "HR", YearsAtCompany = 10 },
new Person { Name = "Fさん", Age = 30, Income = 500, Department = "Dev", YearsAtCompany = 6 },
new Person { Name = "Gさん", Age = 25, Income = 450, Department = "HR", YearsAtCompany = 1 },
};
クエリ式:
var query =
from person in people
orderby
person.Age,
person.Income descending,
person.Department,
person.YearsAtCompany descending
select person.Name;
メソッド式:
var query = people
.OrderBy(person => person.Age)
.ThenByDescending(person => person.Income)
.ThenBy(person => person.Department)
.ThenByDescending(person => person.YearsAtCompany)
.Select(person => person.Name);
結果:
Dさん
Bさん
Gさん
Fさん
Aさん
Cさん
Eさん
所感:
文字量の問題で若干クエリ式の可読性が高い?
5.集約を行う場合
データ:
var products = new[]
{
new Product { Name = "Apple", Category = "Fruit" },
new Product { Name = "Banana", Category = "Fruit" },
new Product { Name = "Carrot", Category = "Vegetable" },
new Product { Name = "Milk", Category = "Dairy" },
new Product { Name = "Cheese", Category = "Dairy" },
};
クエリ式:
var query =
from p in products
group p.Name by p.Category into g
select new { Category = g.Key, Count = g.Count(), Names = g.ToArray() };
メソッド式:
var query = products
.GroupBy(p => p.Category, p => p.Name)
.Select(g => new { Category = g.Key, Count = g.Count(), Names = g.ToArray() });
結果:
Fruit: 2 -> [Apple, Banana]
Vegetable: 1 -> [Carrot]
Dairy: 2 -> [Milk, Cheese]
所感:
クエリ式の構文は「group xxx by yyy」で
「xxx を yyy で集約する」。というのが若干わかりやすい?
6.リスト内包表記
2025/09/18 追記 : @いぬいぬ さん ご意見ありがとうございます。
データ:
var nums = new int[] { 1, 2, 3, 4, 5 };
クエリ式:
List<int> list = [.. from num in nums where num % 2 == 0 select num];
メソッド式:
List<int> list = [.. nums.Where(num=> num % 2 == 0)];
さいごに
最後まで読んでいただき、ありがとうございました。
個人的には上記の記述達はクエリ式が見やすいと感じていますが
チーム内でスタイルを統一しつつ、適材適所で使い分けるのが重要だと思います。
他にも「ここはクエリ式が良い」「この書き換え方がある」などあれば教えていただけると嬉しいです。🤩
Discussion
「リスト内包表記」風にするのはクエリ式の方が見やすいと思います!
ご意見ありがとうございます。
記事に追加させていただきました🙂↕️
途中で変数使うならクエリ式の方がやりやすいみたいなのもありますね。
※ linq to sql などの
IQueryable<T>環境 とかだと ラムダ式が強要される都合 ブロックにすることができず変数の発生が難しい為こんにちは、ご意見ありがとうございます。
ここで言われているのは、IQueryableの場合
以下のはSQLとして動くけどいまいち。
んで、こんなのはSQLとして動かない。
以下の記述が最良のコード
クエリ式良い感じ✌️という認識であってますか?
そうです。だいたいそうです。
動かないというか 式しか許容されないので 文を書くとエラーになる ……でしょうか。
なので下記はコンパイルが通らなかったりします。(※
IQueryable<T>の場合すみません 通常 WarningAsError enable 環境でやっているので、 通常は warning で実行エラーの可能性もあります がご容赦。
👍