C# Tips | コレクション・LINQ:All判定

C# C#
スポンサーリンク

はじめに:「All 判定」は“全員ちゃんと条件を満たしているか?”を見るチェックリスト

Any が「1人でもそういう人がいるか?」を見るメソッドだとしたら、
All は「全員ちゃんとルールを守れているか?」を見るメソッドです。

業務だと、こういう問いがよく出てきます。

「この明細、全部金額が 0 以上になっている?」
「この一覧、全員ステータスが『有効』のものだけになっている?」
「このファイルのレコード、全部フォーマットが正しい?」

こういう「全部ちゃんと条件を満たしているか?」を一発で判定できるのが All です。
ここから、初心者向けに

  • All の基本的な意味
  • Any との違い
  • 空コレクションのときの“意外な挙動”
  • 実務での使いどころと注意点

を、例題付きでかみ砕いて説明していきます。


All の基本:「全員が条件を満たしていれば true」

まずはシンプルな例でイメージをつかむ

using System;
using System.Collections.Generic;
using System.Linq;

var numbers = new List<int> { 2, 4, 6 };

bool allEven = numbers.All(x => x % 2 == 0);

Console.WriteLine(allEven); // true
C#

All(x => 条件) は、「すべての要素がその条件を満たしていれば true、1つでも満たさないものがあれば false」です。

var numbers2 = new List<int> { 2, 3, 4 };

bool allEven2 = numbers2.All(x => x % 2 == 0);

Console.WriteLine(allEven2); // false(3 が偶数じゃない)
C#

ここでの重要ポイントは、「All は“全員チェック”」だということです。
Any が「1人でもいれば true」なのに対し、All は「1人でもダメな人がいたら false」です。


Any と All の関係を感覚でつかむ

「1人でもいるか?」 vs 「全員そうか?」

同じ条件でも、AnyAll で意味が変わります。

var numbers = new List<int> { 2, 3, 4 };

bool hasOdd  = numbers.Any(x => x % 2 != 0); // 奇数が1つでもあるか?
bool allOdd  = numbers.All(x => x % 2 != 0); // 全員奇数か?

Console.WriteLine(hasOdd); // true(3 がいる)
Console.WriteLine(allOdd); // false(2,4 が偶数)
C#
  • Any は「条件を満たす人が1人でもいれば true」
  • All は「全員が条件を満たしていれば true」

この対比を頭に入れておくと、読み書きが一気に楽になります。


一番ハマりやすいポイント:空コレクションの All は true になる

直感とズレやすい挙動

All で一番重要なのは、「要素が 0 件のときどうなるか」です。

var empty = new List<int>();

bool result = empty.All(x => x > 0);

Console.WriteLine(result); // true
C#

「え、要素がないのに true なの?」と感じるかもしれません。
でも、All の意味を言葉にするとこうです。

「すべての要素が条件を満たしているか?」

要素が 1 つもない場合、「条件を満たしていない要素」は存在しません。
なので、「条件を満たしていない要素は1つもない → 全員条件を満たしているとみなす」という扱いになります。
これを数学では「真(vacuum truth)」と呼びます。

ここでの重要ポイントは、「All は“空なら true”になる」という仕様を、ちゃんと知っておくことです。
この挙動を知らないと、「明細が1件もないのに、All が true になってしまった」という事故が起きます。

「空はダメ」にしたいときは Any と組み合わせる

「全員条件を満たしている」だけでなく、「そもそも1件以上あること」も保証したい場合は、Any と組み合わせます。

var lines = new List<int>(); // 明細

bool isValid =
    lines.Any() &&              // 1件以上ある
    lines.All(x => x > 0);      // 全員金額 > 0

Console.WriteLine(isValid); // false(Any が false)
C#

ここでの重要ポイントは、「All だけでは“空でも true”になるので、“1件以上あること”も条件にしたいなら Any() をセットで使う」ということです。


実務での All 判定の典型パターン

例1:明細の金額が全部 0 以上かチェックする

public class OrderLine
{
    public string Item { get; set; } = "";
    public int Amount { get; set; }
}
C#
var lines = new List<OrderLine>
{
    new OrderLine { Item = "A", Amount = 100 },
    new OrderLine { Item = "B", Amount = 200 },
};
C#

「金額がマイナスの明細が1件でもあったらエラー」というチェックは、こう書けます。

bool allNonNegative = lines.All(x => x.Amount >= 0);

if (!allNonNegative)
{
    throw new InvalidOperationException("金額がマイナスの明細があります。");
}
C#

ここでの重要ポイントは、「“全員が条件を満たしているか”という業務ルールを、そのまま All で表現できる」ということです。

もし「明細が1件もないのはエラー」としたいなら、こうなります。

bool isValid =
    lines.Any() &&
    lines.All(x => x.Amount >= 0);

if (!isValid)
{
    throw new InvalidOperationException("明細がないか、金額が不正です。");
}
C#

例2:一覧のステータスが全部「有効」かどうか

public class User
{
    public string Id { get; set; } = "";
    public string Status { get; set; } = ""; // "Active" / "Inactive"
}
C#
var users = new List<User>
{
    new User { Id = "U001", Status = "Active" },
    new User { Id = "U002", Status = "Active" },
};
C#

「この一覧は“有効ユーザーだけ”で構成されているか?」をチェックするなら、こうです。

bool allActive = users.All(u => u.Status == "Active");

if (!allActive)
{
    Console.WriteLine("無効ユーザーが混ざっています。");
}
C#

「1件でも無効ユーザーがいたら NG」というルールと、All の意味がぴったり一致しています。


All を使うときに意識してほしい設計のポイント

「全員チェック」なのか「1人でもダメなら NG」なのかを日本語で言う

All を使う前に、必ず自分にこう問いかけてください。

「この条件は、“全員が満たしていないとダメ”な条件か?」

例えば、

「全明細の金額が 0 以上であること」
「全ユーザーのメールアドレスが空でないこと」
「全レコードのフォーマットが正しいこと」

こういう「1人でも違反者がいたら NG」というルールなら、All がしっくりきます。

逆に、「1人でも該当者がいれば OK」というルールなら、それは Any の出番です。

「空のときどうするか」を必ず決める

All を使うときに一番大事なのは、「空コレクションのときの扱い」を最初に決めることです。

空でも true でいい(「違反者はいない」とみなしてよい)
空は NG にしたい(「そもそもデータがないのはおかしい」)

空を NG にしたいなら、必ず Any() と組み合わせてください。

bool ok = list.Any() && list.All(x => 条件);
C#

ここでの重要ポイントは、「All の“空なら true”という仕様を前提に、業務ルール側でどう扱うかを決める」ことです。


All と Count の組み合わせを避ける

「全員条件を満たしているか」を Count で書かない

たまに、こういう書き方を見かけます。

bool allValid = list.Count(x => 条件) == list.Count();
C#

意味としては「条件を満たす件数が全件数と同じなら、全員条件を満たしている」ということですが、
これは All で素直に書いたほうが読みやすく、パフォーマンスも良いです。

bool allValid = list.All(x => 条件);
C#

Count を使うと、全件を最後まで数える必要がありますが、
All は「条件を満たさない要素を見つけた瞬間に false を返して止まる」ので、途中で終わることができます。

ここでの重要ポイントは、「“全員チェック”を Count で書かず、All で書く習慣をつける」ことです。
読む人にも意図が伝わりやすくなります。


まとめ:「All 判定ユーティリティ」は“全員がルールを守れているかを一発で見る道具」

All の本質は、

「このコレクションの中に、“ルール違反者が1人もいない”ことを確かめる」

ことです。

押さえておきたいポイントは、

  • All(x => 条件) は「全員が条件を満たしていれば true、1人でも満たさなければ false」
  • Any が「1人でもいるか?」、All は「全員そうか?」
  • 空コレクションに対しては All は true になる(ここが一番の落とし穴)
  • 空を NG にしたいなら、Any() と組み合わせて list.Any() && list.All(...) と書く
  • 「全員チェック」を Count で書かず、All で素直に書く

ここまで腹落ちしていれば、
「なんとなく Where と Count で頑張る」段階から一歩進んで、
“業務ルールそのものが読める All 判定”を、落ち着いて書けるようになります。

タイトルとURLをコピーしました