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

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

はじめに:「Any 判定」は“あるか・ないか”を一瞬で決めるスイッチ

業務コードを書いていると、こんなことを知りたくなる場面が山ほどあります。

「このリスト、1件でも入ってる?」
「この条件を満たすデータって、1件でも存在する?」
「このユーザーに権限レコードが1つでもあるかどうかだけ知りたい」

ここで毎回「件数を数える」のは重いし、そもそも「1件でもあればいい」だけなら件数は要りません。
そこで出てくるのが LINQ の Any です。
Any は、「1件でもあるか?」を、最短で判定するためのメソッドです。

ここから、初心者向けに

Any の基本
条件付き Any
Count との違いとパフォーマンス
実務での「Any 判定」ユーティリティ的な使い方

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


Any の基本:「1件でもあれば true」

まずは「空かどうか」を調べる

一番シンプルな使い方は、「コレクションが空かどうか」を調べることです。

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

var list = new List<int> { 1, 2, 3 };

bool hasAny = list.Any();

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

要素が1件でもあれば true、0件なら false です。

var empty = new List<int>();

bool hasAny2 = empty.Any();

Console.WriteLine(hasAny2); // false
C#

ここでの重要ポイントは、「Any() は“1件でもあれば true”という、存在チェック専用のメソッド」だということです。
「何件あるか」は教えてくれません。「あるか・ないか」だけを教えてくれます。

Count > 0 と何が違うのか

初心者がよくやる書き方に、こういうものがあります。

if (list.Count > 0)
{
    // 何かある
}
C#

動きとしては Any() と同じですが、内部的には違いがあります。
Count は「全件数を数える」ことが目的なので、IEnumerable<T> に対しては最後まで全部なめることがあります。
一方 Any() は、「1件見つかった時点で即終了」します。

要素が100万件あるとき、「1件でもあればいい」だけなのに100万件全部数えるのは無駄です。
Any() は、最初の1件を見つけた瞬間に「ある」と判断して止まるので、パフォーマンス的にも素直です。

ここでの重要ポイントは、「“あるかどうか”を知りたいときは Count > 0 ではなく Any() を使う」という習慣をつけることです。


条件付き Any:「この条件を満たすものが1件でもあるか?」

Where + Any ではなく、Any(条件) と書ける

「リスト全体に対して」ではなく、「条件を満たす要素が1件でもあるか」を調べたいことも多いです。
例えば、「金額が 1000 円以上の明細が1件でもあるか?」を調べる場合。

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

こう書きたくなります。

bool exists = lines.Where(x => x.Amount >= 1000).Any();
C#

これはこれで正しいのですが、LINQ には「条件付き Any」が用意されています。

bool exists = lines.Any(x => x.Amount >= 1000);

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

ここでの重要ポイントは、「Any(predicate) というオーバーロードを使うと、Where(...).Any() を1ステップで書ける」ということです。
読みやすさもパフォーマンスも、Any(x => 条件) のほうが素直です。

条件付き Any の「途中で止まる」性質

Any(x => 条件) も、「条件を満たす要素を見つけた瞬間に止まる」という性質を持っています。

例えば、100万件のリストの先頭に条件を満たす要素が1件だけある場合、
Any(x => 条件) はほぼ一瞬で終わります。
Where(x => 条件).Count() のように書いてしまうと、最後まで全部見てしまうので、無駄が大きくなります。

「条件を満たすものが1件でもあるかどうかだけ知りたい」なら、
Any(x => 条件) 一択でいい、という感覚を持っておくとよいです。


実務でよく使う Any 判定のパターン

「存在チェック」としての Any

業務コードで一番よく出てくるのは、「存在チェック」としての Any です。

例えば、「このユーザーに権限レコードが1件でもあるか?」を調べる場合。

public class Role
{
    public string UserId { get; set; } = "";
    public string RoleName { get; set; } = "";
}
C#
var roles = new List<Role>
{
    new Role { UserId = "U001", RoleName = "Admin" },
    new Role { UserId = "U002", RoleName = "User" },
};
C#

ユーザー U001 に何かしらの権限があるかどうかを調べます。

bool hasRole = roles.Any(r => r.UserId == "U001");

if (!hasRole)
{
    Console.WriteLine("権限がありません。");
}
C#

ここでの重要ポイントは、「“あるかどうか”だけ知りたいときは、FirstOrDefault ではなく Any を使う」ということです。
FirstOrDefault で実体を取ってきて null チェックするより、
Any で存在だけ見てから、必要なら別途取得するほうが意図が明確になります。

「バリデーション」としての Any

入力チェックや業務ルールの検証でも、Any はよく使います。

例えば、「同じ商品コードが2回以上出てきたらエラー」というルールがあるとします。

var codes = new[] { "A001", "A002", "A001" };

bool hasDuplicate = codes
    .GroupBy(x => x)
    .Any(g => g.Count() > 1);

if (hasDuplicate)
{
    Console.WriteLine("商品コードが重複しています。");
}
C#

ここでは、「重複しているグループが1つでもあるか?」を Any で判定しています。
「1つでもあればエラー」というルールと、Any の意味がぴったり一致しています。


Any と Count の違いをもう一歩深掘りする

「件数が欲しい」のか「あるかどうかだけ知りたい」のか

AnyCount は、初心者のうちにきちんと頭の中で分けておくと、後々かなり効いてきます。

件数が欲しいとき(「何件あるか」を使うロジックがあるとき)は Count
あるかどうかだけ知りたいときは Any

例えば、「明細が1件もない注文はエラー」というチェックを書くとします。

悪い例はこうです。

if (orderLines.Count == 0)
{
    throw new InvalidOperationException("明細が1件もありません。");
}
C#

動きとしては正しいですが、「“0件かどうか”を知りたいだけなのに、わざわざ件数を数えている」状態です。

素直に書くなら、こうです。

if (!orderLines.Any())
{
    throw new InvalidOperationException("明細が1件もありません。");
}
C#

ここでの重要ポイントは、「コードを読む人に“何を知りたいのか”が伝わる書き方をする」ことです。
Any と書いてあれば、「この人は“あるかどうか”だけを見ているんだな」と一目で分かります。

データベース LINQ(LINQ to Entities)でも Any は重要

Entity Framework などで DB に対して LINQ を投げる場合も、Any は重要です。

例えば、

var exists = db.Users.Any(u => u.Id == userId);
C#

これは SQL にすると、だいたいこういう形になります。

SELECT CASE WHEN EXISTS (
    SELECT 1 FROM Users WHERE Id = @userId
) THEN CAST(1 AS bit) ELSE CAST(0 AS bit) END

一方、Count を使うと、こうなりがちです。

var count = db.Users.Count(u => u.Id == userId);
bool exists = count > 0;
C#

SQL 的には

SELECT COUNT(*) FROM Users WHERE Id = @userId

となり、「件数を数える」クエリになります。
存在チェックだけしたいのに、わざわざ件数を数えるのは無駄です。

ここでの重要ポイントは、「DB に対しても、“存在チェックは Any”という癖をつけておくと、自然と効率の良いクエリになる」ということです。


Any 判定をユーティリティとしてどう使うか

「なかったらどうするか」をセットで考える

Any は「あるか・ないか」を教えてくれるだけなので、「ないときどうするか」は自分で決める必要があります。

例えば、「明細が1件もない注文はエラーにする」なら、こうです。

if (!orderLines.Any())
{
    throw new InvalidOperationException("明細が1件もありません。");
}
C#

「明細が1件もない場合は、合計金額 0 として扱う」なら、こうです。

int total = orderLines.Any()
    ? orderLines.Sum(x => x.Amount)
    : 0;
C#

ここでの重要ポイントは、「Any は“スイッチ”であって、“処理そのもの”ではない」ということです。
Any でスイッチを作り、「true のときはこうする」「false のときはこうする」を自分で設計します。

「Any でガードしてから、重い処理をする」というパターン

業務では、「そもそも対象データが1件もなければ、重い処理をスキップしたい」という場面も多いです。

if (orders.Any())
{
    // 重い集計処理
    var result = orders
        .GroupBy(o => o.CustomerId)
        .Select(g => new
        {
            CustomerId = g.Key,
            Total = g.Sum(x => x.Amount)
        })
        .ToList();

    // 結果をどこかに保存
}
C#

Any で「そもそも対象があるか」を先に見ておくことで、
無駄な集計や DB アクセスを避けられます。


まとめ:「Any 判定ユーティリティ」は“存在を最短で確かめるための道具”

Any の本質は、

「このコレクション(あるいは条件を満たす要素)は、
 “1件でも存在するのか”を、最短で確かめる」

ことです。

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

Any() は「1件でもあれば true、なければ false」
Count > 0 ではなく Any() を使うと、意図もパフォーマンスも素直になる
条件付きなら Any(x => 条件) と書く(Where(...).Any() より読みやすい)
DB に対する存在チェックでも Any は重要
Any はスイッチなので、「ないときどうするか」をセットで設計する

ここまで腹落ちしていれば、
「なんとなく Count で書いてしまう」段階から卒業して、
“存在チェックは Any で書く”という、業務コードらしい書き方に一段レベルアップできます。

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