C# Any()の使い方を徹底解説|LINQで存在チェックする方法・Count()との違い・注意点
はじめに
C#でコレクションの中に「1件でもデータがあるか」「条件に一致する要素が存在するか」を調べたいときによく使うのが、LINQのAny()メソッドです。
たとえば、ユーザー一覧に対象ユーザーが存在するか、商品リストに在庫ありの商品が含まれているか、文字列リストに特定のキーワードを含む要素があるか、といった判定に使えます。
Any()は戻り値がboolで、存在すればtrue、存在しなければfalseを返します。要素そのものを取得するのではなく、「存在するかどうか」だけを知りたい場面に向いたメソッドです。Microsoftの公式ドキュメントでも、Any()はシーケンスに要素が存在するか、または条件を満たす要素があるかを判定するメソッドとして説明されています。
1. C#のAny()とは?LINQで存在チェックする基本メソッド
1-1. Any()は「1件でも存在するか」をboolで返すメソッド
Any()は、配列やList<T>などのコレクションに対して「要素が1件でも存在するか」を判定するLINQメソッドです。
C#var numbers = new List<int> { 1, 2, 3 };
bool result = numbers.Any();
Console.WriteLine(result); // True
この例では、numbersに要素が1件以上あるため、Any()はtrueを返します。
空のリストであればfalseになります。
C#var numbers = new List<int>();
bool result = numbers.Any();
Console.WriteLine(result); // False
Any()は「要素を取り出す」メソッドではなく、「存在するかどうかを確認する」メソッドです。そのため、戻り値は常にboolです。
1-2. Any()でできること:空チェック・条件一致チェック・データ有無の判定
Any()には大きく分けて2つの使い方があります。
1つ目は、条件なしでコレクションが空かどうかを判定する使い方です。
C#if (items.Any())
{
Console.WriteLine("データがあります");
}
2つ目は、条件を指定して、その条件に一致する要素があるかを判定する使い方です。
C#if (users.Any(user => user.IsActive))
{
Console.WriteLine("有効なユーザーがいます");
}
条件付きのAny()は、Any(predicate)とも呼ばれます。predicateとは、各要素に対してtrueまたはfalseを返す条件式のことです。
1-3. Any()を使うために必要なSystem.Linq
Any()はLINQの拡張メソッドなので、通常はファイルの先頭でSystem.Linqを読み込む必要があります。
C#using System.Linq;
.NET 6以降のプロジェクトでは、暗黙的なusingによって明示的に書かなくても使える場合があります。ただし、古いプロジェクトや設定によってはusing System.Linq;がないとAny()が見つかりません。
LINQの標準クエリ演算子は、IEnumerable<T>を実装するデータソースに対してクエリ処理を行うためのメソッド群です。Any()もその代表的なメソッドの1つです。
1-4. Any()が使える主な型:List・配列・IEnumerable・IQueryable
Any()は、主に次のような型で使えます。
| 型 | 使用例 |
|---|---|
List<T> | users.Any() |
| 配列 | numbers.Any() |
IEnumerable<T> | items.Any() |
IQueryable<T> | db.Users.Any() |
List<T>や配列は、日常的なC#コードでよく使うコレクションです。IEnumerable<T>はLINQの基本となるインターフェイスで、IQueryable<T>はEntity Frameworkなどでデータベースクエリを組み立てるときによく使われます。
2. C# Any()の基本的な使い方
2-1. 条件なしのAny()でコレクションが空かどうかを判定する
条件なしのAny()は、コレクションに要素が1件でもあるかを調べます。
C#var names = new List<string> { "Alice", "Bob" };
if (names.Any())
{
Console.WriteLine("名前が登録されています");
}
else
{
Console.WriteLine("名前が登録されていません");
}
空チェックでは、次のようにCount() > 0と書くこともできます。
C#if (names.Count() > 0)
{
Console.WriteLine("名前が登録されています");
}
しかし、存在確認が目的ならAny()のほうが意図が明確です。
C#if (names.Any())
{
Console.WriteLine("名前が登録されています");
}
「件数を知りたい」のではなく「存在するか知りたい」場合は、Any()を使うと読みやすくなります。
2-2. 条件ありのAny(predicate)で一致する要素があるか判定する
条件付きのAny()では、ラムダ式を使って条件を指定します。
C#var numbers = new List<int> { 1, 2, 3, 4, 5 };
bool hasEven = numbers.Any(n => n % 2 == 0);
Console.WriteLine(hasEven); // True
この例では、偶数が1件でもあればtrueになります。2や4が条件を満たすため、結果はtrueです。
条件に一致する要素がない場合はfalseになります。
C#var numbers = new List<int> { 1, 3, 5 };
bool hasEven = numbers.Any(n => n % 2 == 0);
Console.WriteLine(hasEven); // False
2-3. ListでAny()を使うサンプルコード
List<T>に対してAny()を使う例です。
C#var products = new List<string>
{
"Keyboard",
"Mouse",
"Monitor"
};
if (products.Any())
{
Console.WriteLine("商品があります");
}
条件を指定する場合は、次のように書けます。
C#bool hasMonitor = products.Any(product => product == "Monitor");
Console.WriteLine(hasMonitor); // True
部分一致を判定したい場合は、Contains()を組み合わせます。
C#bool hasKey = products.Any(product => product.Contains("Key"));
Console.WriteLine(hasKey); // True
2-4. 配列でAny()を使うサンプルコード
配列でもAny()を使えます。
C#int[] scores = { 80, 95, 60 };
bool hasHighScore = scores.Any(score => score >= 90);
Console.WriteLine(hasHighScore); // True
文字列配列でも同じです。
C#string[] names = { "Sato", "Suzuki", "Tanaka" };
bool exists = names.Any(name => name == "Suzuki");
Console.WriteLine(exists); // True
配列に要素があるかだけを見たいなら、次のように書けます。
C#if (names.Any())
{
Console.WriteLine("名前があります");
}
ただし、配列の単純な空判定だけならnames.Length > 0も有力な選択肢です。この点は後ほどパフォーマンスの章で解説します。
2-5. オブジェクトのプロパティを条件にしてAny()を使う方法
実務では、単純な数値や文字列だけでなく、オブジェクトのプロパティを条件にしてAny()を使う場面が多くあります。
C#public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public bool IsActive { get; set; }
}
ユーザー一覧の中に有効なユーザーがいるかを判定します。
C#var users = new List<User>
{
new User { Id = 1, Name = "Alice", IsActive = true },
new User { Id = 2, Name = "Bob", IsActive = false }
};
bool hasActiveUser = users.Any(user => user.IsActive);
Console.WriteLine(hasActiveUser); // True
特定のIDを持つユーザーが存在するかも簡単に判定できます。
C#int targetId = 2;
bool exists = users.Any(user => user.Id == targetId);
Console.WriteLine(exists); // True
3. Any()を使った実践的な存在チェックパターン
3-1. 特定の文字列が含まれる要素を探す
文字列リストの中に、特定のキーワードを含む要素があるか調べる例です。
C#var titles = new List<string>
{
"C#入門",
"LINQの使い方",
"ASP.NET Core解説"
};
bool hasLinqTitle = titles.Any(title => title.Contains("LINQ"));
Console.WriteLine(hasLinqTitle); // True
大文字・小文字を無視して検索したい場合は、StringComparisonを使うと意図が明確です。
C#bool hasCsharp = titles.Any(title =>
title.Contains("c#", StringComparison.OrdinalIgnoreCase));
日本語中心の検索では大文字小文字の問題は少ないですが、英数字を含む検索では意識しておくと安全です。
3-2. 数値リストに条件を満たす値があるか調べる
数値の一覧から、条件を満たす値があるかを判定できます。
C#var prices = new List<int> { 1200, 3000, 500, 9800 };
bool hasExpensiveItem = prices.Any(price => price >= 5000);
Console.WriteLine(hasExpensiveItem); // True
在庫数のようなデータにも使えます。
C#var stocks = new List<int> { 0, 0, 5, 0 };
bool hasStock = stocks.Any(stock => stock > 0);
Console.WriteLine(hasStock); // True
このように、Any()は「条件を満たす値が1つでもあるか」を自然に表現できます。
3-3. ユーザー一覧に特定IDのユーザーが存在するか確認する
ユーザーIDや商品IDの存在確認は、Any()の典型的な使いどころです。
C#int userId = 10;
bool userExists = users.Any(user => user.Id == userId);
if (userExists)
{
Console.WriteLine("対象ユーザーが存在します");
}
else
{
Console.WriteLine("対象ユーザーが存在しません");
}
このコードは、usersの中にIdが10のユーザーが1件でもあればtrueを返します。
ログイン処理、権限チェック、重複登録チェックなどでもよく使われます。
C#string email = "test@example.com";
bool alreadyRegistered = users.Any(user => user.Email == email);
if (alreadyRegistered)
{
Console.WriteLine("このメールアドレスはすでに登録されています");
}
3-4. ネストしたコレクションでAny()を使う
コレクションの中にさらにコレクションがある場合にもAny()は便利です。
C#public class Order
{
public int Id { get; set; }
public List<OrderItem> Items { get; set; } = new();
}
public class OrderItem
{
public string ProductName { get; set; } = "";
public int Quantity { get; set; }
}
注文一覧の中に、数量が10以上の商品を含む注文があるか調べます。
C#bool hasLargeOrder = orders.Any(order =>
order.Items.Any(item => item.Quantity >= 10));
外側のAny()は「条件を満たす注文があるか」を判定し、内側のAny()は「その注文の明細に条件を満たす商品があるか」を判定しています。
ネストが深くなると読みにくくなるため、条件が複雑な場合はメソッド化するとよいでしょう。
C#bool HasLargeItem(Order order)
{
return order.Items.Any(item => item.Quantity >= 10);
}
bool hasLargeOrder = orders.Any(HasLargeItem);
3-5. if文の条件式でAny()を読みやすく使う書き方
Any()はif文の条件式にそのまま書くと読みやすくなります。
C#if (orders.Any(order => order.Status == "Pending"))
{
Console.WriteLine("未処理の注文があります");
}
否定する場合は、!Any()を使います。
C#if (!orders.Any())
{
Console.WriteLine("注文がありません");
}
条件付きで否定することもできます。
C#if (!users.Any(user => user.IsAdmin))
{
Console.WriteLine("管理者ユーザーが存在しません");
}
ただし、否定条件が複雑になりすぎると読みにくくなります。
C#if (!users.Any(user => !user.IsActive && user.LastLoginDate < limitDate))
{
// 読みにくくなりやすい
}
このような場合は、条件を変数やメソッドに分けると理解しやすくなります。
C#bool IsInactiveOldUser(User user)
{
return !user.IsActive && user.LastLoginDate < limitDate;
}
if (!users.Any(IsInactiveOldUser))
{
Console.WriteLine("長期間未使用の無効ユーザーはいません");
}
4. Any()とCount()の違い
4-1. Any()は存在確認、Count()は件数取得に使う
Any()とCount()は似た場面で使われますが、目的が異なります。
Any()は「存在するかどうか」を調べるメソッドです。
C#bool exists = users.Any();
一方、Count()は「件数」を取得するメソッドです。
C#int count = users.Count();
つまり、知りたいことが「1件でもあるか」ならAny()、知りたいことが「何件あるか」ならCount()です。Count()は指定したシーケンス内の要素数、または条件を満たす要素数を返すメソッドとして定義されています。
4-2. Count() > 0よりAny()が推奨される理由
次の2つは、多くの場合、結果だけを見ると同じです。
C#users.Count() > 0
C#users.Any()
しかし、存在確認が目的ならAny()が推奨されます。理由は、コードの意図が明確で、不要な件数計算を避けやすいからです。
C#if (users.Any())
{
Console.WriteLine("ユーザーが存在します");
}
このコードは、「ユーザーが1件でも存在するか」を直接表現しています。
一方で、次のコードは「件数を数えて、それが0より大きいか」を表しています。
C#if (users.Count() > 0)
{
Console.WriteLine("ユーザーが存在します");
}
存在確認のためだけに件数を数えるのは、意図として少し遠回りです。
4-3. Any()は条件に一致した時点で処理を終了できる
Any()は、結果が判断できた時点で列挙を止められます。公式ドキュメントでも、Any()は結果を判定できるとすぐに列挙を停止すると説明されています。
たとえば、100万件のデータがあっても、最初の1件が条件を満たせばそこで判定できます。
C#bool hasError = logs.Any(log => log.Level == "Error");
先頭付近でErrorが見つかれば、それ以降の要素を確認する必要はありません。
4-4. Count()は件数を数えるため全体を走査する場合がある
Count()は件数を返すメソッドなので、IEnumerable<T>の種類によっては全体を走査する場合があります。
C#bool exists = items.Count() > 0;
このコードでは、本当は「1件でもあるか」だけを知りたいのに、件数を求める形になっています。
Microsoftのコード分析ルールCA1827でも、少なくとも1つの要素があるかを確認する目的でCount()やLongCount()を使うと指摘対象になり、Any()を使うことで不要な列挙を避けられると説明されています。
4-5. Countプロパティ・Lengthプロパティ・Count()メソッドの違い
C#では、似た名前のCountやLengthが複数あります。
C#list.Count // List<T>のプロパティ
array.Length // 配列のプロパティ
items.Count() // LINQのメソッド
List<T>のCountプロパティや配列のLengthプロパティは、コレクション自身が保持している件数を返します。
C#var list = new List<int> { 1, 2, 3 };
Console.WriteLine(list.Count); // 3
int[] array = { 1, 2, 3 };
Console.WriteLine(array.Length); // 3
一方、Count()はLINQの拡張メソッドです。
C#IEnumerable<int> numbers = GetNumbers();
int count = numbers.Count();
IEnumerable<T>に対してCount()を使う場合、データソースによっては列挙が発生します。配列やList<T>の単純な件数取得では、LengthやCountプロパティのほうが適していることがあります。MicrosoftのCA1829でも、同等のLengthまたはCountプロパティを持つ型では、LINQのCount()よりプロパティの使用が推奨されています。
4-6. Any()とCount()の使い分け早見表
| やりたいこと | 推奨される書き方 |
|---|---|
| 1件でも存在するか知りたい | items.Any() |
| 条件に一致する要素があるか知りたい | items.Any(x => 条件) |
| 件数そのものが必要 | items.Count() |
List<T>の件数が必要 | list.Count |
| 配列の要素数が必要 | array.Length |
| 空でないことを確認したい | items.Any()または型に応じてCount > 0、Length > 0 |
| 条件に一致する件数が必要 | items.Count(x => 条件) |
基本方針は、「存在確認ならAny()、件数取得ならCount()」です。
5. Any()と似たメソッドとの違い
5-1. Any()とWhere()の違い:存在確認か抽出か
Any()は存在確認、Where()は抽出に使います。
C#bool exists = users.Any(user => user.IsActive);
これは、有効なユーザーが存在するかをboolで返します。
一方、Where()は条件に一致する要素を取り出します。
C#var activeUsers = users.Where(user => user.IsActive);
Where()の戻り値はコレクションです。Microsoftのドキュメントでも、Where()は述語に基づいてシーケンスをフィルター処理し、条件を満たす要素を返すメソッドとして説明されています。
存在確認だけなら、次のように書くよりも、
C#users.Where(user => user.IsActive).Any()
次のように書くほうが簡潔です。
C#users.Any(user => user.IsActive)
5-2. Any()とContains()の違い:単純一致か条件判定か
Contains()は、指定した値そのものがシーケンスに含まれているかを判定します。
C#var names = new List<string> { "Alice", "Bob" };
bool exists = names.Contains("Alice");
Any()は、より柔軟な条件判定ができます。
C#bool exists = names.Any(name => name.StartsWith("A"));
単純に値が含まれるかを見たいだけならContains()が自然です。
C#ids.Contains(targetId)
プロパティや複雑な条件で判定したい場合はAny()が向いています。
C#users.Any(user => user.Id == targetId)
Contains()は既定の等値比較子、または指定した比較子を使って、シーケンスに指定要素が含まれるかを判定するメソッドです。
5-3. Any()とFirstOrDefault()の違い:存在確認か要素取得か
Any()は存在確認に使います。
C#bool exists = users.Any(user => user.Id == targetId);
FirstOrDefault()は、条件に一致する最初の要素を取得したいときに使います。
C#User? user = users.FirstOrDefault(user => user.Id == targetId);
存在するかだけを知りたいのにFirstOrDefault()を使うと、意図が少し曖昧になります。
C#if (users.FirstOrDefault(user => user.Id == targetId) != null)
{
Console.WriteLine("存在します");
}
この場合は、Any()のほうが読みやすいです。
C#if (users.Any(user => user.Id == targetId))
{
Console.WriteLine("存在します");
}
ただし、存在確認後にその要素を使うなら、FirstOrDefault()で取得したほうが二度手間を避けられます。
C#var user = users.FirstOrDefault(user => user.Id == targetId);
if (user != null)
{
Console.WriteLine(user.Name);
}
5-4. Any()とAll()の違い:1件でも一致か全件一致か
Any()は「1件でも条件を満たすか」を判定します。
C#bool hasAdult = users.Any(user => user.Age >= 18);
All()は「すべての要素が条件を満たすか」を判定します。
C#bool allAdults = users.All(user => user.Age >= 18);
意味は大きく異なります。
C#var ages = new List<int> { 20, 17, 30 };
bool anyAdult = ages.Any(age => age >= 18); // True
bool allAdults = ages.All(age => age >= 18); // False
1人でも成人がいればよいならAny()、全員が成人である必要があるならAll()です。All()は、シーケンスのすべての要素が条件を満たすかを判定するメソッドです。
5-5. Any()とExists()の違い:LINQメソッドかList専用メソッドか
Exists()はList<T>に用意されているメソッドです。
C#bool exists = users.Exists(user => user.IsActive);
Any()はLINQの拡張メソッドで、List<T>だけでなく、配列やIEnumerable<T>、IQueryable<T>などでも使えます。
C#bool exists = users.Any(user => user.IsActive);
List<T>.Exists()は、指定した条件に一致する要素がList<T>に含まれているかを判定するメソッドです。
チーム開発では、LINQで統一するためにAny()を使うことが多いです。ただし、List<T>に限定された処理で、既存コードがExists()を使っているなら、それに合わせる判断もあります。
6. Any()を使うときの注意点
6-1. nullのコレクションにAny()を使うと例外になる
Any()を使うときに注意したいのが、対象のコレクションがnullの場合です。
C#List<string>? names = null;
bool exists = names.Any(); // 例外
Any()は空のコレクションには安全に使えますが、nullのコレクションにはそのまま使えません。
C#var emptyNames = new List<string>();
Console.WriteLine(emptyNames.Any()); // False
「空」と「null」は別物です。空のリストは要素数が0のコレクションですが、nullはコレクションそのものが存在しない状態です。
6-2. nullチェックとAny()を安全に組み合わせる方法
nullの可能性がある場合は、次のようにチェックします。
C#if (names != null && names.Any())
{
Console.WriteLine("名前があります");
}
null条件演算子を使う方法もあります。
C#if (names?.Any() == true)
{
Console.WriteLine("名前があります");
}
この書き方は、namesがnullならnames?.Any()がnullになり、== trueを満たさないため安全です。
空リストとして扱いたい場合は、Enumerable.Empty<T>()を使う方法もあります。
C#var safeNames = names ?? Enumerable.Empty<string>();
if (safeNames.Any())
{
Console.WriteLine("名前があります");
}
メソッドの引数で受け取る場合は、可能であればnullではなく空のコレクションを渡す設計にすると、呼び出し側のコードがシンプルになります。
6-3. Any()の条件式に副作用のある処理を書かない
Any()の条件式には、基本的に副作用のある処理を書かないほうが安全です。
悪い例です。
C#int count = 0;
bool exists = users.Any(user =>
{
count++;
return user.IsActive;
});
Any()は条件を満たす要素が見つかった時点で処理を止めるため、countが全件分増えるとは限りません。
ログ出力、カウンタ更新、外部API呼び出し、データ更新などをAny()の中に書くと、実行回数が直感とずれる可能性があります。
条件式は、できるだけ「判定だけ」にしましょう。
C#bool exists = users.Any(user => user.IsActive);
6-4. 遅延実行されるIEnumerableでのAny()の挙動に注意する
LINQには遅延実行されるメソッドがあります。Where()やSelect()などは、定義しただけでは処理が実行されず、列挙されたタイミングで実行されます。
C#var query = users.Where(user => user.IsActive);
bool exists = query.Any();
この場合、Any()を呼び出したタイミングでWhere()の条件が評価されます。
LINQの多くのメソッドは、クエリオブジェクトが列挙されるまで対象データを使用しない遅延実行の性質を持ちます。一方、Any()のように単一の値を返す操作は、呼び出し時に結果を得るために列挙を実行します。
6-5. 複数回Any()を呼ぶと再列挙が発生する場合がある
IEnumerable<T>に対してAny()を複数回呼ぶと、そのたびに列挙が発生する場合があります。
C#IEnumerable<User> query = GetUsers();
if (query.Any(user => user.IsActive))
{
Console.WriteLine("有効ユーザーがいます");
}
if (query.Any(user => user.IsAdmin))
{
Console.WriteLine("管理者がいます");
}
GetUsers()の実装によっては、2回列挙されることで無駄が発生します。データベースや外部リソースに関わる処理では特に注意が必要です。
必要であれば、一度リスト化してから使います。
C#var userList = GetUsers().ToList();
bool hasActive = userList.Any(user => user.IsActive);
bool hasAdmin = userList.Any(user => user.IsAdmin);
ただし、データベースクエリでは安易にToList()すると大量データをメモリに読み込む可能性があります。どこで列挙するかを意識しましょう。
6-6. 空判定だけならCount・Length・IsEmptyプロパティが適する場合もある
Any()は存在確認に便利ですが、配列やList<T>など、件数を高速に取得できる型ではLengthやCountプロパティが適する場合もあります。
C#if (array.Length > 0)
{
Console.WriteLine("配列に要素があります");
}
if (list.Count > 0)
{
Console.WriteLine("リストに要素があります");
}
MicrosoftのCA1860では、Length、Count、IsEmptyプロパティを持つコレクションでは、空判定にEnumerable.Any()ではなく、それらのプロパティを使う修正が提示されています。
ただし、IEnumerable<T>として受け取っている場合や、型が具体的でない場合は、Any()のほうが自然です。
7. LINQ to SQL・Entity FrameworkでAny()を使う場合
7-1. IQueryableでAny()を使うとSQLに変換される
Entity Framework CoreなどでIQueryable<T>に対してAny()を使うと、LINQクエリがデータベースプロバイダーによってSQLなどのデータベース固有のクエリに変換されます。EF CoreはLINQを使ってデータベースを問い合わせ、LINQクエリの表現をデータベースプロバイダーへ渡し、プロバイダーがSQLなどへ変換します。
C#bool exists = dbContext.Users.Any(user => user.Email == email);
このコードは、C#のコレクションをメモリ上で全件処理しているわけではありません。dbContext.UsersがIQueryable<User>であれば、データベース側で存在確認を行うクエリとして実行されます。
Queryableクラスは、IQueryable<T>を実装するデータソースに対して標準クエリ演算子を提供します。
7-2. データベースの存在チェックではAny()が有効な理由
データベースで「存在するか」を確認したい場合、Any()は非常に自然な選択です。
C#bool emailExists = dbContext.Users
.Any(user => user.Email == email);
件数が必要ないのにCount()を使うと、コードの意図が「件数取得」に見えてしまいます。
C#bool emailExists = dbContext.Users
.Count(user => user.Email == email) > 0;
存在確認であれば、Any()を使うことで「1件でもあればよい」という意図が明確になります。
7-3. ToList()してからAny()するのを避けるべきケース
Entity Frameworkでよくある悪い例が、先にToList()してからAny()する書き方です。
C#bool exists = dbContext.Users
.ToList()
.Any(user => user.Email == email);
このコードでは、まずUsersのデータをメモリ上に読み込んでから、C#側でAny()を実行します。ユーザー数が多い場合、無駄なデータ取得やメモリ消費につながります。
存在確認だけなら、次のように書きます。
C#bool exists = dbContext.Users
.Any(user => user.Email == email);
この書き方なら、存在確認の条件をデータベースクエリとして表現できます。
7-4. 非同期処理ではAnyAsync()を使う
ASP.NET CoreなどのWebアプリケーションでは、データベースアクセスを非同期で行うことが多くあります。その場合はAnyAsync()を使います。
C#using Microsoft.EntityFrameworkCore;
bool exists = await dbContext.Users
.AnyAsync(user => user.Email == email);
AnyAsync()は、シーケンスに要素が含まれるか、または条件を満たす要素があるかを非同期的に判定するEntity Framework Coreの拡張メソッドです。
キャンセルトークンを渡すこともできます。
C#bool exists = await dbContext.Users
.AnyAsync(user => user.Email == email, cancellationToken);
Web APIやバックグラウンド処理では、非同期メソッドを適切に使うことで、スレッドをブロックしにくい実装にできます。
7-5. Entity FrameworkでAny()を使うときの注意点
Entity FrameworkでAny()を使うときは、次の点に注意しましょう。
まず、SQLに変換できないC#メソッドを条件式に含めないことです。
C#bool exists = dbContext.Users
.Any(user => IsTargetUser(user)); // 変換できない可能性がある
このような独自メソッドは、データベースプロバイダーがSQLに変換できない場合があります。可能であれば、式の中に直接条件を書きます。
C#bool exists = dbContext.Users
.Any(user => user.IsActive && user.Role == "Admin");
また、ToList()、AsEnumerable()などで途中からメモリ上の処理に切り替えないようにしましょう。
C#// 大量データでは避けたい
bool exists = dbContext.Users
.AsEnumerable()
.Any(user => user.Email == email);
データベースで判定できる条件は、できるだけIQueryable<T>のままAny()に渡すのが基本です。
8. Any()のパフォーマンスを理解する
8-1. Any()が高速になりやすい仕組み
Any()が高速になりやすい理由は、結果が分かった時点で処理を止められるからです。
C#bool exists = items.Any(item => item.IsValid);
この場合、最初にIsValidがtrueの要素を見つけた時点で、残りの要素を見る必要がありません。
一方、件数を正確に数える処理では、条件を満たす要素が何件あるかを確認する必要があります。
C#int count = items.Count(item => item.IsValid);
「存在するか」だけなら、全件の件数は不要です。
8-2. 大量データでCount() > 0よりAny()が有利なケース
大量データのIEnumerable<T>では、Count() > 0よりAny()のほうが有利になる場面があります。
C#bool exists = largeItems.Any();
Any()は1件見つかれば判定できます。
C#bool exists = largeItems.Count() > 0;
Count()は、データソースによっては件数を求めるために全体を列挙する可能性があります。
特に、ファイルから1行ずつ読み込む処理、外部APIから順番に取得する処理、yield returnで生成されるシーケンスなどでは、Any()のほうが意図にも性能にも合いやすいです。
8-3. Listや配列ではCount・Lengthプロパティも選択肢になる
一方で、常にAny()だけが最適とは限りません。
List<T>ならCountプロパティ、配列ならLengthプロパティがあります。
C#if (list.Count > 0)
{
Console.WriteLine("リストに要素があります");
}
if (array.Length > 0)
{
Console.WriteLine("配列に要素があります");
}
これらはコレクションが持つ件数情報を直接参照するため、単純な空判定では十分に明確で効率的です。
IEnumerable<T>として扱っているならAny()、具体的にList<T>や配列だと分かっているならCountやLengthも選択肢、と考えるとよいでしょう。
8-4. パフォーマンスよりも意図が伝わるコードを優先する考え方
パフォーマンスは重要ですが、ほとんどの業務コードでは、まず「意図が伝わるか」を優先することが大切です。
存在確認なら、次のコードはとても読みやすいです。
C#if (users.Any(user => user.IsActive))
{
Console.WriteLine("有効なユーザーがいます");
}
件数が必要なら、次のコードが自然です。
C#int activeUserCount = users.Count(user => user.IsActive);
無理にすべてを最速にしようとするより、目的に合ったメソッドを選ぶことが、保守性の高いコードにつながります。
8-5. コード分析ルールで指摘されるAny()とCount()の使い分け
.NETのコード分析では、Any()とCount()の使い分けに関するルールがあります。
代表的なのがCA1827です。これは、少なくとも1件あるかを確認するためにCount()やLongCount()を使っている場合に、Any()の使用を促すルールです。
C#// 指摘されやすい
if (items.Count() > 0)
{
}
// 推奨されやすい
if (items.Any())
{
}
一方で、CA1860では、Length、Count、IsEmptyプロパティを持つコレクションに対して、空判定でEnumerable.Any()を使うより、それらのプロパティを使うことが提案されます。
つまり、単純に「常にAny()」ではなく、型と目的に応じて選ぶことが大切です。
9. Any()のよくあるエラーと解決方法
9-1. 「Anyが見つからない」と表示される原因
Any()を使おうとして、次のようなエラーが出ることがあります。
'IEnumerable<T>' does not contain a definition for 'Any'
主な原因は、System.Linqが読み込まれていないことです。
C#using System.Linq;
C#のLINQ拡張メソッドは、名前空間を読み込むことで使えるようになります。
9-2. using System.Linqが不足している場合の対処法
ファイルの先頭に次を追加します。
C#using System.Linq;
.NET 6以降のテンプレートでは暗黙的なusingが有効になっていることもありますが、プロジェクト設定によっては必要です。
また、Any()を使っている対象が本当にコレクションかも確認しましょう。
C#User user = new User();
// user.Any() は使えない
Any()は単体のオブジェクトではなく、IEnumerable<T>などのシーケンスに対して使います。
9-3. NullReferenceExceptionが発生する原因
Any()でエラーが起きる場合、対象がnullになっている可能性があります。
C#List<string>? names = null;
if (names.Any())
{
}
このようなコードは安全ではありません。Enumerable.Any()自体はsourceがnullの場合に引数エラーになりますが、実務上はプロパティチェーンの途中がnullでNullReferenceExceptionになるケースもあります。
C#if (user.Orders.Any())
{
}
この例では、userまたはuser.Ordersがnullなら例外が発生する可能性があります。
安全に書くなら、次のようにします。
C#if (user?.Orders?.Any() == true)
{
Console.WriteLine("注文があります");
}
または、Ordersを初期値で空リストにしておく設計も有効です。
C#public List<Order> Orders { get; set; } = new();
9-4. 条件式の書き方を間違えたときの修正例
条件式では、代入演算子=と比較演算子==の間違いに注意しましょう。
悪い例です。
C#bool exists = users.Any(user => user.Id = targetId);
正しくは次のように書きます。
C#bool exists = users.Any(user => user.Id == targetId);
文字列比較では、必要に応じて大文字小文字の扱いも意識します。
C#bool exists = users.Any(user =>
string.Equals(user.Email, email, StringComparison.OrdinalIgnoreCase));
複数条件は&&や||でつなげます。
C#bool exists = users.Any(user =>
user.IsActive && user.Role == "Admin");
条件が長くなったら、読みやすさのためにメソッド化しましょう。
C#bool IsActiveAdmin(User user)
{
return user.IsActive && user.Role == "Admin";
}
bool exists = users.Any(IsActiveAdmin);
9-5. IQueryableで期待どおりに動かないときの確認ポイント
IQueryable<T>でAny()が期待どおりに動かない場合は、次の点を確認します。
まず、途中でToList()やAsEnumerable()を呼んでいないか確認します。
C#// データベースではなくメモリ上で評価される可能性がある
dbContext.Users
.AsEnumerable()
.Any(user => user.Email == email);
次に、条件式にSQLへ変換できない独自メソッドが入っていないか確認します。
C#dbContext.Users.Any(user => Normalize(user.Email) == email);
このような場合、プロバイダーが変換できずエラーになることがあります。
可能であれば、データベースに変換しやすい単純な条件にします。
C#dbContext.Users.Any(user => user.Email == email);
また、非同期処理ではAny()ではなくAnyAsync()を使っているかも確認しましょう。
C#bool exists = await dbContext.Users.AnyAsync(user => user.Email == email);
10. Any()の読みやすい書き方とベストプラクティス
10-1. Count() > 0ではなくAny()で意図を明確にする
存在確認では、基本的にCount() > 0ではなくAny()を使います。
C#// 避けたい
if (users.Count() > 0)
{
}
C#// 読みやすい
if (users.Any())
{
}
条件付きでも同じです。
C#// 避けたい
if (users.Count(user => user.IsActive) > 0)
{
}
C#// 読みやすい
if (users.Any(user => user.IsActive))
{
}
「存在するか」を表したいなら、Any()がもっとも直接的です。
10-2. 条件が複雑な場合はメソッド化する
条件が長くなると、Any()の中が読みにくくなります。
C#bool exists = users.Any(user =>
user.IsActive &&
user.Role == "Admin" &&
user.LastLoginDate >= DateTime.Today.AddDays(-30));
この程度なら読めますが、さらに条件が増えるならメソッド化しましょう。
C#bool IsRecentlyActiveAdmin(User user)
{
return user.IsActive
&& user.Role == "Admin"
&& user.LastLoginDate >= DateTime.Today.AddDays(-30);
}
bool exists = users.Any(IsRecentlyActiveAdmin);
条件に名前が付くことで、コードの意図が明確になります。
10-3. Where().Any()よりAny(predicate)を使う
次のようなコードは動作します。
C#bool exists = users
.Where(user => user.IsActive)
.Any();
しかし、存在確認だけならAny(predicate)のほうが簡潔です。
C#bool exists = users.Any(user => user.IsActive);
Where()は抽出、Any()は存在確認です。抽出結果を使わないなら、最初からAny()に条件を書きましょう。
10-4. 否定条件では!Any()を使って空や未存在を表現する
要素が存在しないことを表したい場合は、!Any()を使います。
C#if (!users.Any())
{
Console.WriteLine("ユーザーがいません");
}
条件に一致する要素が存在しないことも表現できます。
C#if (!users.Any(user => user.IsActive))
{
Console.WriteLine("有効なユーザーがいません");
}
ただし、否定条件が読みにくい場合は変数に分けるとよいです。
C#bool hasActiveUser = users.Any(user => user.IsActive);
if (!hasActiveUser)
{
Console.WriteLine("有効なユーザーがいません");
}
10-5. チーム開発で統一したいAny()の書き方
チーム開発では、Any()の使い方を統一しておくとレビューしやすくなります。
たとえば、次のようなルールが考えられます。
| ルール | 例 |
|---|---|
存在確認はAny()を使う | items.Any() |
条件付き存在確認はAny(predicate)を使う | users.Any(u => u.IsActive) |
Where().Any()は避ける | users.Any(u => u.IsActive) |
件数が必要な場合だけCount()を使う | users.Count() |
配列の空判定はLength > 0も許可 | array.Length > 0 |
List<T>の空判定はCount > 0も許可 | list.Count > 0 |
| nullの可能性がある場合は安全に書く | items?.Any() == true |
ルールを厳密にしすぎる必要はありませんが、「なぜその書き方を選んだのか」が伝わるコードを目指すことが大切です。
11. C# Any()に関するよくある質問
11-1. Any()は空のリストでfalseを返しますか?
はい。空のリストに対してAny()を呼ぶとfalseを返します。
C#var list = new List<int>();
Console.WriteLine(list.Any()); // False
空のリストはnullではないため、例外にはなりません。
11-2. Any()はnullのリストでも使えますか?
そのままでは使えません。
C#List<int>? list = null;
bool exists = list.Any(); // 例外
安全に書くなら、次のようにします。
C#bool exists = list?.Any() == true;
または、空リストとして扱います。
C#bool exists = (list ?? Enumerable.Empty<int>()).Any();
11-3. Any()とCount() > 0は結果が同じですか?
多くの場合、存在確認の結果としては同じです。
C#items.Any()
items.Count() > 0
どちらも要素が1件以上あればtrueになります。
ただし、目的と処理の意味が異なります。Any()は存在確認、Count()は件数取得です。存在確認だけならAny()のほうが意図が明確で、不要な列挙を避けやすいです。
11-4. Any()とContains()はどちらを使うべきですか?
単純に値が含まれているかを調べるならContains()が自然です。
C#bool exists = ids.Contains(targetId);
条件を指定したい場合や、オブジェクトのプロパティを見たい場合はAny()を使います。
C#bool exists = users.Any(user => user.Id == targetId);
単純一致ならContains()、条件判定ならAny()と考えると分かりやすいです。
11-5. Any()はforeachより速いですか?
Any()は内部的には列挙を行うため、手書きのforeachと考え方は近いです。
C#bool exists = false;
foreach (var item in items)
{
if (item.IsValid)
{
exists = true;
break;
}
}
これは、次のAny()と同じような意図です。
C#bool exists = items.Any(item => item.IsValid);
大きな違いは、Any()のほうが簡潔で意図が伝わりやすいことです。極端な最適化が必要な場面を除けば、存在確認にはAny()を使うのが一般的です。
11-6. Any()は配列にも使えますか?
はい。配列にもAny()は使えます。
C#int[] numbers = { 1, 2, 3 };
bool exists = numbers.Any();
Console.WriteLine(exists); // True
条件付きでも使えます。
C#bool hasEven = numbers.Any(n => n % 2 == 0);
Console.WriteLine(hasEven); // True
ただし、配列の単純な空判定だけなら、Lengthプロパティも分かりやすいです。
C#if (numbers.Length > 0)
{
Console.WriteLine("要素があります");
}
まとめ
Any()は、C#のLINQで「1件でも存在するか」を判定するための基本メソッドです。戻り値はboolで、要素が存在すればtrue、存在しなければfalseを返します。
条件なしのAny()はコレクションの空チェックに使えます。
C#items.Any()
条件付きのAny(predicate)は、条件に一致する要素が1件でもあるかを判定できます。
C#items.Any(item => item.IsActive)
Count() > 0でも同じような結果を得られる場合はありますが、存在確認が目的ならAny()のほうが意図が明確です。件数そのものが必要な場合はCount()、配列やList<T>の単純な空判定ではLengthやCountプロパティも選択肢になります。
また、Entity FrameworkではAny()やAnyAsync()を使うことで、データベースに対する存在確認を自然に表現できます。ToList()してからAny()するのではなく、可能な限りIQueryable<T>のまま条件を指定することが重要です。
最後に、Any()を使うときは、nullのコレクションに注意し、条件式には副作用を持たせないようにしましょう。存在確認を読みやすく、効率よく書くために、Any()はC#開発で必ず押さえておきたいメソッドです。

