C# Existsの使い方完全ガイド|List・File・Directoryの存在チェックとAnyとの違いを解説
はじめに
C#で「存在するかどうか」を判定したい場面は非常に多くあります。たとえば、リストの中に条件に合うデータがあるか確認したり、指定したファイルが存在するか調べたり、フォルダがなければ作成したりするケースです。
このような存在チェックでよく使われるのが、Existsです。
ただし、C#のExistsにはいくつか種類があります。代表的なものは、List<T>.Exists、File.Exists、Directory.Existsです。それぞれ用途が異なり、同じ「Exists」という名前でも使い方や対象が違います。
また、コレクションの存在チェックではLINQのAnyと比較されることも多く、「ExistsとAnyは何が違うのか」「どちらを使えばよいのか」で迷う人も少なくありません。
この記事では、C#のExistsの基本から、List、File、Directoryでの使い方、Anyとの違い、よくあるエラー、実務で使えるコード例までわかりやすく解説します。
1. C#のExistsとは?用途別に存在チェックを理解しよう
1-1. Existsは「存在するか」をboolで判定するメソッド
C#におけるExistsは、名前の通り「存在するかどうか」を判定するためのメソッドです。
多くの場合、戻り値はbool型です。つまり、条件に合うものが存在すればtrue、存在しなければfalseを返します。
たとえば、リストの中に特定の値があるか調べる場合は、次のように書けます。
C#var numbers = new List<int> { 1, 2, 3, 4, 5 };
bool exists = numbers.Exists(n => n == 3);
Console.WriteLine(exists); // True
この例では、リスト内に3が存在するため、Existsはtrueを返します。
存在チェックの結果をif文で使えば、条件に応じて処理を分岐できます。
C#if (numbers.Exists(n => n == 3))
{
Console.WriteLine("3が存在します");
}
Existsは「あるかないか」だけを知りたいときに使いやすいメソッドです。
1-2. C#で使われる主なExists:List・File・Directory
C#でよく使われるExistsには、主に次の3種類があります。
C#List<T>.Exists
File.Exists
Directory.Exists
List<T>.Existsは、リスト内に条件を満たす要素があるかどうかを調べるメソッドです。
C#list.Exists(x => 条件)
File.Existsは、指定したパスにファイルが存在するかどうかを調べるメソッドです。
C#File.Exists("ファイルパス")
Directory.Existsは、指定したパスにディレクトリ、つまりフォルダが存在するかどうかを調べるメソッドです。
C#Directory.Exists("フォルダパス")
同じExistsでも、対象がリストなのか、ファイルなのか、フォルダなのかによって使い方が異なります。
1-3. Existsメソッドが必要になる代表的な場面
Existsは、実務でも頻繁に使われます。代表的な場面は次のようなケースです。
ユーザー一覧の中に指定したユーザーがいるか確認する場合。
C#bool userExists = users.Exists(user => user.Id == targetId);
設定ファイルが存在するか確認する場合。
C#bool fileExists = File.Exists("settings.json");
ログ出力用のフォルダが存在するか確認する場合。
C#bool directoryExists = Directory.Exists("logs");
条件に合うデータがある場合だけ処理を実行したいときにも使えます。
C#if (orders.Exists(order => order.Status == "未処理"))
{
Console.WriteLine("未処理の注文があります");
}
このように、Existsは「処理を始める前の確認」として使われることが多いです。
1-4. まず押さえるべき戻り値true/falseの考え方
Existsを理解するうえで重要なのは、戻り値がtrueまたはfalseであることです。
trueは「存在する」、falseは「存在しない」を意味します。
C#bool result = File.Exists("sample.txt");
if (result)
{
Console.WriteLine("ファイルがあります");
}
else
{
Console.WriteLine("ファイルがありません");
}
Existsは、対象そのものを返すわけではありません。たとえば、List<T>.Existsは条件に一致した要素を返すのではなく、「条件に一致する要素があるかどうか」だけを返します。
条件に一致した要素そのものを取得したい場合は、FindやFirstOrDefaultなどを使います。
C#var user = users.Find(u => u.Id == targetId);
一方で、「存在確認だけできればよい」という場面では、Existsがシンプルで読みやすい選択肢になります。
2. List<T>.Existsの使い方|リスト内の要素存在チェック
2-1. List<T>.Existsの基本構文
List<T>.Existsは、リストの中に条件を満たす要素が1つでも存在するかどうかを判定します。
基本構文は次の通りです。
C#bool result = list.Exists(条件);
実際には、ラムダ式を使って条件を書くことが多いです。
C#bool result = list.Exists(item => item == 条件値);
たとえば、数値リストの中に10があるか調べる場合は、次のように書きます。
C#var numbers = new List<int> { 5, 10, 15 };
bool exists = numbers.Exists(n => n == 10);
Console.WriteLine(exists); // True
Existsは条件に一致する要素を見つけると、その時点でtrueを返します。最後まで探しても見つからなければfalseを返します。
2-2. 文字列リストで特定の値が存在するか判定する
文字列リストでもExistsはよく使われます。
C#var fruits = new List<string> { "apple", "banana", "orange" };
bool exists = fruits.Exists(fruit => fruit == "banana");
Console.WriteLine(exists); // True
この例では、fruitsの中に"banana"が存在するため、結果はtrueです。
大文字小文字を区別せずに比較したい場合は、StringComparisonを使うと安全です。
C#var fruits = new List<string> { "Apple", "Banana", "Orange" };
bool exists = fruits.Exists(fruit =>
string.Equals(fruit, "banana", StringComparison.OrdinalIgnoreCase));
Console.WriteLine(exists); // True
単純にfruit.ToLower() == "banana"のように書く方法もありますが、文字列比較ではstring.EqualsにStringComparisonを指定する方が意図が明確です。
2-3. 数値リストで条件に一致する要素を探す
Existsでは、完全一致だけでなく条件式も指定できます。
たとえば、リスト内に偶数が存在するか調べる場合は次のように書けます。
C#var numbers = new List<int> { 1, 3, 5, 8, 9 };
bool hasEven = numbers.Exists(n => n % 2 == 0);
Console.WriteLine(hasEven); // True
8が偶数なので、hasEvenはtrueになります。
一定以上の値があるかを判定することもできます。
C#var scores = new List<int> { 45, 60, 72, 88 };
bool hasHighScore = scores.Exists(score => score >= 80);
Console.WriteLine(hasHighScore); // True
このように、Existsは「特定の値があるか」だけでなく、「条件に合う要素があるか」を調べるのに向いています。
2-4. オブジェクトのプロパティを条件にExistsで検索する
実務では、単純な数値や文字列よりも、オブジェクトのリストに対してExistsを使う場面が多いです。
たとえば、次のようなUserクラスがあるとします。
C#public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public bool IsActive { get; set; }
}
ユーザー一覧の中に、指定したIDのユーザーが存在するか確認するには次のように書きます。
C#var users = new List<User>
{
new User { Id = 1, Name = "田中", IsActive = true },
new User { Id = 2, Name = "佐藤", IsActive = false },
new User { Id = 3, Name = "鈴木", IsActive = true }
};
int targetId = 2;
bool exists = users.Exists(user => user.Id == targetId);
Console.WriteLine(exists); // True
有効なユーザーが存在するか確認する場合は、次のように書けます。
C#bool hasActiveUser = users.Exists(user => user.IsActive);
Console.WriteLine(hasActiveUser); // True
user => user.IsActive == trueと書いても動きますが、IsActive自体がbool型なので、user => user.IsActiveの方が簡潔です。
2-5. Predicate<T>とラムダ式の書き方
List<T>.Existsの引数には、Predicate<T>を渡します。
Predicate<T>とは、指定した型の値を受け取り、boolを返す条件式のことです。
C#Predicate<int> isEven = n => n % 2 == 0;
このPredicate<int>をExistsに渡せます。
C#var numbers = new List<int> { 1, 2, 3 };
Predicate<int> isEven = n => n % 2 == 0;
bool exists = numbers.Exists(isEven);
Console.WriteLine(exists); // True
もちろん、通常は直接ラムダ式を書くことが多いです。
C#bool exists = numbers.Exists(n => n % 2 == 0);
条件が短い場合はラムダ式を直接書くと読みやすくなります。
一方で、条件が複雑な場合は、メソッドに切り出すと可読性が上がります。
C#static bool IsTargetUser(User user)
{
return user.IsActive && user.Name.StartsWith("田");
}
bool exists = users.Exists(IsTargetUser);
処理内容が複雑になってきたら、無理に1行で書かず、意味のある名前を付けてメソッド化すると保守しやすくなります。
2-6. Existsがtrue/falseを返す具体例
Existsの戻り値を具体例で確認してみましょう。
C#var numbers = new List<int> { 10, 20, 30 };
bool result1 = numbers.Exists(n => n == 20);
bool result2 = numbers.Exists(n => n == 99);
bool result3 = numbers.Exists(n => n > 25);
bool result4 = numbers.Exists(n => n < 0);
Console.WriteLine(result1); // True
Console.WriteLine(result2); // False
Console.WriteLine(result3); // True
Console.WriteLine(result4); // False
それぞれの結果は次のように考えます。
n == 20を満たす要素は存在するためtrueです。
n == 99を満たす要素は存在しないためfalseです。
n > 25を満たす30が存在するためtrueです。
n < 0を満たす要素は存在しないためfalseです。
空のリストに対してExistsを実行した場合は、必ずfalseになります。
C#var emptyList = new List<int>();
bool exists = emptyList.Exists(n => n > 0);
Console.WriteLine(exists); // False
空のリストには条件を満たす要素が1つもないためです。
3. File.Existsの使い方|ファイルの存在チェック
3-1. File.Existsの基本構文
File.Existsは、指定したパスにファイルが存在するかどうかを判定します。
使用するには、System.IO名前空間が必要です。
C#using System.IO;
基本構文は次の通りです。
C#bool exists = File.Exists("ファイルパス");
たとえば、sample.txtというファイルが存在するか確認する場合は、次のように書きます。
C#bool exists = File.Exists("sample.txt");
if (exists)
{
Console.WriteLine("ファイルが存在します");
}
else
{
Console.WriteLine("ファイルが存在しません");
}
File.Existsはファイル専用です。フォルダの存在確認には使いません。
3-2. 指定したファイルパスが存在するか確認する
絶対パスを指定してファイルの存在を確認する例です。
C#string path = @"C:\temp\sample.txt";
if (File.Exists(path))
{
Console.WriteLine("ファイルがあります");
}
else
{
Console.WriteLine("ファイルがありません");
}
Windowsのパスでは\を使うため、文字列の前に@を付けると書きやすくなります。
C#string path = @"C:\temp\sample.txt";
@を付けない場合は、\をエスケープする必要があります。
C#string path = "C:\\temp\\sample.txt";
どちらの書き方でも動作しますが、ファイルパスでは@を使った逐語的文字列リテラルがよく使われます。
3-3. 相対パスと絶対パスでのFile.Existsの違い
File.Existsには、相対パスと絶対パスのどちらも指定できます。
絶対パスは、ドライブ名やルートから始まる完全なパスです。
C#string absolutePath = @"C:\temp\sample.txt";
相対パスは、現在の作業ディレクトリを基準にしたパスです。
C#string relativePath = "sample.txt";
相対パスを使う場合、基準になるのはソースコードが置かれている場所とは限りません。多くの場合、実行時のカレントディレクトリが基準になります。
現在の作業ディレクトリを確認するには、次のように書けます。
C#Console.WriteLine(Directory.GetCurrentDirectory());
相対パスでFile.Existsがfalseになる場合は、実行時の基準フォルダが想定と違っていることがよくあります。
確実に指定したい場合は、絶対パスを使うか、Path.Combineで基準ディレクトリからパスを組み立てるのがおすすめです。
C#string baseDir = AppContext.BaseDirectory;
string path = Path.Combine(baseDir, "sample.txt");
bool exists = File.Exists(path);
3-4. ファイルが存在しない場合に作成する処理
ファイルが存在しない場合に新しく作成するには、File.ExistsとFile.WriteAllTextなどを組み合わせます。
C#string path = "settings.txt";
if (!File.Exists(path))
{
File.WriteAllText(path, "初期設定");
Console.WriteLine("ファイルを作成しました");
}
else
{
Console.WriteLine("ファイルは既に存在します");
}
!File.Exists(path)は、「ファイルが存在しない場合」という意味です。
空のファイルを作成したい場合は、File.Createも使えます。
C#string path = "empty.txt";
if (!File.Exists(path))
{
using FileStream fs = File.Create(path);
}
File.CreateはFileStreamを返すため、使い終わったら閉じる必要があります。上記のようにusingを使うと、安全にリソースを解放できます。
3-5. File.Existsがfalseになる主な原因
File.Existsがfalseを返す主な原因には、次のようなものがあります。
まず、指定したファイルが本当に存在しない場合です。
C#File.Exists("notfound.txt"); // False
次に、パスが間違っている場合です。ファイル名のスペルミス、拡張子の違い、フォルダ階層の指定ミスなどがよくあります。
C#File.Exists("sample.text"); // 本当は sample.txt なら False
相対パスの基準フォルダが想定と違う場合もfalseになります。
C#File.Exists("data/sample.txt");
この場合、dataフォルダがどこを基準に探されているのか確認する必要があります。
また、指定したパスがフォルダの場合、File.Existsはfalseを返します。フォルダの存在確認にはDirectory.Existsを使います。
C#bool result = File.Exists(@"C:\temp"); // C:\temp がフォルダなら False
アクセス権限やパスの形式が原因で、存在しているように見えてもfalseになるケースもあります。
3-6. null・空文字・無効なパスを指定した場合の挙動
File.Existsにnullを渡した場合、例外ではなくfalseが返ります。
C#string? path = null;
bool exists = File.Exists(path);
Console.WriteLine(exists); // False
空文字を渡した場合もfalseです。
C#bool exists = File.Exists("");
Console.WriteLine(exists); // False
無効なパスを指定した場合も、多くの場合はfalseになります。
C#bool exists = File.Exists("???");
Console.WriteLine(exists); // False
ただし、ファイル操作全体では例外が発生する可能性があります。File.Existsがfalseを返すからといって、その後のファイル作成や読み込みが必ず安全に実行できるわけではありません。
ファイルを読み書きする処理では、try-catchによる例外処理もあわせて考える必要があります。
4. Directory.Existsの使い方|フォルダの存在チェック
4-1. Directory.Existsの基本構文
Directory.Existsは、指定したパスにディレクトリが存在するかどうかを判定します。
使用するには、File.Existsと同じくSystem.IO名前空間を使います。
C#using System.IO;
基本構文は次の通りです。
C#bool exists = Directory.Exists("ディレクトリパス");
たとえば、logsフォルダが存在するか確認する場合は、次のように書きます。
C#string directoryPath = "logs";
if (Directory.Exists(directoryPath))
{
Console.WriteLine("フォルダが存在します");
}
else
{
Console.WriteLine("フォルダが存在しません");
}
4-2. 指定したディレクトリが存在するか確認する
絶対パスを使ってディレクトリの存在を確認する例です。
C#string path = @"C:\temp\logs";
bool exists = Directory.Exists(path);
Console.WriteLine(exists);
存在していればtrue、存在していなければfalseです。
相対パスも指定できます。
C#string path = "logs";
if (Directory.Exists(path))
{
Console.WriteLine("logsフォルダがあります");
}
相対パスの場合は、File.Existsと同じく実行時のカレントディレクトリが基準になる点に注意しましょう。
C#Console.WriteLine(Directory.GetCurrentDirectory());
4-3. フォルダが存在しない場合に作成する処理
フォルダが存在しない場合に作成するには、Directory.ExistsとDirectory.CreateDirectoryを組み合わせます。
C#string directoryPath = "logs";
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
Console.WriteLine("フォルダを作成しました");
}
else
{
Console.WriteLine("フォルダは既に存在します");
}
ただし、Directory.CreateDirectoryは、対象のディレクトリが既に存在していても例外にはなりません。そのため、単純に作成したいだけなら、存在チェックを省略して次のように書くこともできます。
C#Directory.CreateDirectory("logs");
この書き方は実務でもよく使われます。存在していなければ作成し、既に存在していればそのまま処理が続きます。
4-4. File.ExistsとDirectory.Existsの使い分け
File.ExistsとDirectory.Existsは、対象によって使い分けます。
ファイルの存在確認にはFile.Existsを使います。
C#File.Exists("sample.txt");
フォルダの存在確認にはDirectory.Existsを使います。
C#Directory.Exists("logs");
間違えて使うと、対象が存在していてもfalseになります。
C#// logs がフォルダの場合
bool result1 = File.Exists("logs"); // False
bool result2 = Directory.Exists("logs"); // True
逆に、sample.txtがファイルの場合は次のようになります。
C#bool result1 = File.Exists("sample.txt"); // True
bool result2 = Directory.Exists("sample.txt"); // False
ファイルかフォルダかがわからない場合は、両方を確認する方法もあります。
C#string path = "sample";
bool exists = File.Exists(path) || Directory.Exists(path);
4-5. Directory.Existsがfalseになる原因
Directory.Existsがfalseになる主な原因は、指定したフォルダが存在しないことです。
C#Directory.Exists("notfound"); // False
パスの指定ミスもよくある原因です。
C#Directory.Exists("log"); // 本当は logs なら False
相対パスの基準フォルダが想定と違う場合もあります。特に、Visual Studioやテスト実行環境では、実行時のカレントディレクトリが思っている場所と異なることがあります。
また、指定したパスがファイルの場合、Directory.Existsはfalseを返します。
C#Directory.Exists("sample.txt"); // sample.txt がファイルなら False
ネットワークパスを指定している場合は、接続状態や権限の影響でfalseになることもあります。
4-6. アクセス権限・パス指定ミス・ネットワークパスの注意点
ディレクトリの存在チェックでは、パス指定だけでなく、アクセス権限にも注意が必要です。
たとえば、アプリケーションを実行しているユーザーに対象フォルダへのアクセス権がない場合、期待通りに存在確認できないことがあります。
ネットワーク共有フォルダを指定する場合は、次のようなUNCパスを使うことがあります。
C#string path = @"\\server\share\logs";
bool exists = Directory.Exists(path);
この場合、サーバーに接続できない、共有名が間違っている、認証情報が不足している、といった理由でfalseになる可能性があります。
また、パスを文字列連結で組み立てると、区切り文字の不足や重複が起きやすくなります。
C#string path = basePath + "\\" + folderName;
より安全に書くなら、Path.Combineを使いましょう。
C#string path = Path.Combine(basePath, folderName);
ファイルやディレクトリを扱う処理では、パスの正確性、アクセス権限、実行環境の違いを意識することが重要です。
5. ExistsとAnyの違い|どちらを使うべきか
5-1. List<T>.ExistsとLINQ Anyの基本的な違い
C#でコレクション内の存在チェックを行う場合、List<T>.ExistsのほかにLINQのAnyもよく使われます。
Existsの例です。
C#var numbers = new List<int> { 1, 2, 3 };
bool exists = numbers.Exists(n => n == 2);
Anyの例です。
C#var numbers = new List<int> { 1, 2, 3 };
bool exists = numbers.Any(n => n == 2);
どちらも「条件に一致する要素が1つでもあるか」を判定できます。
大きな違いは、ExistsはList<T>のメソッドであり、AnyはLINQの拡張メソッドである点です。
5-2. ExistsはList<T>専用、AnyはIEnumerable<T>で使える
List<T>.Existsは、名前の通りList<T>に用意されているメソッドです。
C#List<int> numbers = new List<int> { 1, 2, 3 };
bool exists = numbers.Exists(n => n == 2);
一方、AnyはIEnumerable<T>に対して使えます。つまり、配列、リスト、LINQの結果、さまざまなコレクションで使用できます。
C#int[] numbers = { 1, 2, 3 };
bool exists = numbers.Any(n => n == 2);
Anyを使うには、System.Linqが必要です。
C#using System.Linq;
IEnumerable<T>として受け取ったデータには、Existsは使えません。
C#IEnumerable<int> numbers = new List<int> { 1, 2, 3 };
// numbers.Exists(n => n == 2); // コンパイルエラー
bool exists = numbers.Any(n => n == 2);
汎用的なコードを書くなら、Anyの方が使いやすい場面が多いです。
5-3. 書き方の違いをコードで比較
ExistsとAnyの書き方を比較してみましょう。
List<T>.Existsの場合です。
C#var users = new List<User>
{
new User { Id = 1, Name = "田中", IsActive = true },
new User { Id = 2, Name = "佐藤", IsActive = false }
};
bool exists = users.Exists(user => user.Id == 1);
Anyの場合です。
C#bool exists = users.Any(user => user.Id == 1);
このように、条件式の書き方はほとんど同じです。
条件なしで「要素が1つでもあるか」を調べたい場合、Anyは次のように書けます。
C#bool hasAny = users.Any();
一方、Existsは条件を渡す必要があります。
C#bool hasAny = users.Exists(user => true);
この書き方は不自然なので、単に要素があるか確認したい場合はAny()を使う方が適しています。
5-4. 可読性・汎用性・保守性で選ぶ基準
ExistsとAnyはどちらも存在チェックに使えますが、選び方には基準があります。
対象が明確にList<T>で、「リスト内に条件に合う要素があるか」を表現したい場合は、Existsでも問題ありません。
C#bool hasAdmin = users.Exists(user => user.Role == "Admin");
一方で、メソッドの引数や戻り値がIEnumerable<T>である場合は、Anyを使うのが自然です。
C#public bool HasAdmin(IEnumerable<User> users)
{
return users.Any(user => user.Role == "Admin");
}
将来的にList<T>以外のコレクションへ変更される可能性があるなら、Anyの方が保守しやすくなります。
また、コード全体でLINQを多く使っている場合は、Anyに統一した方が読みやすいこともあります。
5-5. パフォーマンス面での違い
ExistsとAnyは、どちらも条件に一致する要素を見つけた時点で探索を終了します。
たとえば、先頭の要素が条件に一致すれば、すべての要素を調べる必要はありません。
C#var numbers = new List<int> { 1, 2, 3, 4, 5 };
bool exists1 = numbers.Exists(n => n == 1);
bool exists2 = numbers.Any(n => n == 1);
このようなケースでは、どちらも早い段階で結果を返します。
厳密には、List<T>.ExistsはList<T>専用に用意されたメソッドで、AnyはLINQの拡張メソッドです。そのため、細かな実装上の違いはあります。
しかし、通常のアプリケーション開発では、パフォーマンス差を気にして選ぶよりも、可読性や汎用性で選ぶ方が重要です。
大量データを扱う場合は、ExistsかAnyかよりも、データ構造や検索方法そのものを見直すべきことが多いです。
たとえば、頻繁に存在チェックを行うなら、List<T>よりHashSet<T>やDictionary<TKey, TValue>の方が適している場合があります。
C#var ids = new HashSet<int> { 1, 2, 3 };
bool exists = ids.Contains(2);
5-6. 実務ではExistsとAnyのどちらを選ぶべきか
実務では、次のように考えると選びやすくなります。
List<T>に対して、単純に条件一致の存在確認をするならExistsで問題ありません。
C#bool exists = users.Exists(user => user.Id == targetId);
配列、IEnumerable<T>、LINQの結果に対して存在確認するならAnyを使います。
C#bool exists = users.Where(user => user.IsActive)
.Any(user => user.Role == "Admin");
ただし、上記は次のようにまとめられます。
C#bool exists = users.Any(user => user.IsActive && user.Role == "Admin");
一般的には、汎用性を重視するならAny、List<T>に限定したシンプルな処理ならExistsと覚えておくとよいでしょう。
6. Existsでよくあるエラー・つまずきポイント
6-1. Existsが使えない・認識されない原因
Existsが使えない原因として多いのは、対象の型がList<T>ではないケースです。
C#IEnumerable<int> numbers = new List<int> { 1, 2, 3 };
// numbers.Exists(n => n == 2); // エラー
ExistsはList<T>のメソッドなので、IEnumerable<T>型の変数には使えません。
この場合はAnyを使います。
C#bool exists = numbers.Any(n => n == 2);
また、配列にもExistsは直接使えません。
C#int[] numbers = { 1, 2, 3 };
// numbers.Exists(n => n == 2); // エラー
配列ではAnyを使うか、Array.Existsを使います。
C#bool exists1 = numbers.Any(n => n == 2);
bool exists2 = Array.Exists(numbers, n => n == 2);
6-2. 配列やIEnumerableでExistsを使おうとして失敗するケース
配列に対してExistsを使おうとして、次のようなコードを書いてしまうことがあります。
C#int[] numbers = { 1, 2, 3 };
bool exists = numbers.Exists(n => n == 2); // コンパイルエラー
配列にはList<T>.Existsがないため、これはコンパイルエラーになります。
配列で存在チェックをするなら、LINQのAnyを使うのが一般的です。
C#using System.Linq;
int[] numbers = { 1, 2, 3 };
bool exists = numbers.Any(n => n == 2);
または、Array.Existsを使えます。
C#int[] numbers = { 1, 2, 3 };
bool exists = Array.Exists(numbers, n => n == 2);
IEnumerable<T>に対しても同じです。
C#IEnumerable<string> names = new List<string> { "田中", "佐藤" };
bool exists = names.Any(name => name == "田中");
Existsが使えないときは、「変数の型が本当にList<T>なのか」を確認しましょう。
6-3. System.IOやSystem.Linqのusing不足
File.ExistsやDirectory.Existsを使うには、通常はSystem.IOを読み込みます。
C#using System.IO;
最近のC#プロジェクトでは暗黙的なusingによって明示しなくても使える場合がありますが、環境によっては必要です。
C#bool fileExists = File.Exists("sample.txt");
bool dirExists = Directory.Exists("logs");
Anyを使うには、System.Linqが必要です。
C#using System.Linq;
Anyが認識されない場合は、using System.Linq;が不足している可能性があります。
C#var numbers = new List<int> { 1, 2, 3 };
bool exists = numbers.Any(n => n == 2);
List<T>を使うには、通常はSystem.Collections.Genericが必要です。
C#using System.Collections.Generic;
名前空間の不足は初心者がつまずきやすいポイントなので、エラーが出たらまずusingを確認しましょう。
6-4. 大文字小文字の違いによるコンパイルエラー
C#は大文字小文字を区別する言語です。
そのため、ExistsをexistsやEXISTSと書くと、別の名前として扱われます。
C#var numbers = new List<int> { 1, 2, 3 };
// numbers.exists(n => n == 2); // エラー
bool exists = numbers.Exists(n => n == 2);
File.ExistsやDirectory.Existsも同じです。
C#bool fileExists = File.Exists("sample.txt");
bool dirExists = Directory.Exists("logs");
次のような書き方は誤りです。
C#// File.exists("sample.txt"); // エラー
// Directory.exists("logs"); // エラー
メソッド名の大文字小文字を正しく書くことが大切です。
6-5. Existsがfalseを返すのに実際は存在するように見える原因
File.ExistsやDirectory.Existsがfalseを返すのに、エクスプローラーでは存在しているように見えることがあります。
よくある原因は、相対パスの基準が想定と違うことです。
C#File.Exists("sample.txt");
このコードは、ソースコードのあるフォルダではなく、実行時のカレントディレクトリを基準に探します。
確認するには、次のコードを使います。
C#Console.WriteLine(Directory.GetCurrentDirectory());
拡張子が違うケースもあります。
C#File.Exists("sample.txt");
実際のファイル名がsample.txt.txtになっている、またはsample.csvだった、ということもあります。
Windowsでは拡張子が非表示になっている場合があるため、ファイル名を正確に確認しましょう。
また、全角・半角の違いや、余分な空白が含まれている場合もあります。
C#string path = "sample.txt ";
このように末尾に空白があると、意図したファイルとは別のパスとして扱われます。
6-6. 存在チェック後に削除・変更される競合状態の注意点
ファイル操作では、File.Existsで存在確認した直後に、別の処理によってファイルが削除される可能性があります。
たとえば、次のコードは一見安全に見えます。
C#if (File.Exists(path))
{
string text = File.ReadAllText(path);
}
しかし、File.Exists(path)がtrueを返した後、File.ReadAllText(path)を実行する前にファイルが削除されると、読み込み時に例外が発生する可能性があります。
そのため、ファイル操作では存在チェックだけに頼らず、例外処理も必要です。
C#try
{
string text = File.ReadAllText(path);
Console.WriteLine(text);
}
catch (FileNotFoundException)
{
Console.WriteLine("ファイルが見つかりませんでした");
}
catch (IOException ex)
{
Console.WriteLine($"ファイルの読み込みに失敗しました: {ex.Message}");
}
存在チェックは便利ですが、「チェックしたから絶対に安全」とは考えないようにしましょう。
7. Existsの実践コード例
7-1. List内に特定ユーザーが存在するか確認する
ユーザー一覧の中に、指定したメールアドレスのユーザーが存在するか確認する例です。
C#public class User
{
public int Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
}
var users = new List<User>
{
new User { Id = 1, Name = "田中", Email = "tanaka@example.com" },
new User { Id = 2, Name = "佐藤", Email = "sato@example.com" }
};
string targetEmail = "sato@example.com";
bool exists = users.Exists(user => user.Email == targetEmail);
if (exists)
{
Console.WriteLine("指定したユーザーは存在します");
}
else
{
Console.WriteLine("指定したユーザーは存在しません");
}
メールアドレスの大文字小文字を区別したくない場合は、次のようにします。
C#bool exists = users.Exists(user =>
string.Equals(user.Email, targetEmail, StringComparison.OrdinalIgnoreCase));
7-2. ファイルがあれば読み込み、なければ作成する
設定ファイルが存在すれば読み込み、存在しなければ作成する例です。
C#string path = "settings.txt";
try
{
if (File.Exists(path))
{
string text = File.ReadAllText(path);
Console.WriteLine("ファイルを読み込みました");
Console.WriteLine(text);
}
else
{
File.WriteAllText(path, "default=true");
Console.WriteLine("ファイルがなかったため作成しました");
}
}
catch (IOException ex)
{
Console.WriteLine($"ファイル操作に失敗しました: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"アクセス権限がありません: {ex.Message}");
}
ファイル操作では、存在確認だけでなく、IOExceptionやUnauthorizedAccessExceptionへの対応も考えておくと安全です。
7-3. フォルダがなければ自動作成する
ログ出力用のフォルダがなければ作成する例です。
C#string logDirectory = "logs";
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
Console.WriteLine("ログフォルダを作成しました");
}
string logFilePath = Path.Combine(logDirectory, "app.log");
File.AppendAllText(logFilePath, "ログを出力しました\n");
ただし、Directory.CreateDirectoryは既にフォルダが存在していても問題なく実行できます。
そのため、次のように書いても構いません。
C#string logDirectory = "logs";
Directory.CreateDirectory(logDirectory);
string logFilePath = Path.Combine(logDirectory, "app.log");
File.AppendAllText(logFilePath, "ログを出力しました\n");
この書き方の方がシンプルで、実務でも使いやすいです。
7-4. ファイルまたはディレクトリのどちらかが存在するか判定する
指定したパスがファイルまたはディレクトリとして存在するか確認したい場合は、File.ExistsとDirectory.Existsを組み合わせます。
C#string path = "data";
bool exists = File.Exists(path) || Directory.Exists(path);
if (exists)
{
Console.WriteLine("ファイルまたはフォルダが存在します");
}
else
{
Console.WriteLine("存在しません");
}
ファイルとフォルダのどちらとして存在しているかを分けて判定することもできます。
C#string path = "data";
if (File.Exists(path))
{
Console.WriteLine("ファイルとして存在します");
}
else if (Directory.Exists(path))
{
Console.WriteLine("フォルダとして存在します");
}
else
{
Console.WriteLine("存在しません");
}
パスの種類に応じて処理を変えたい場合に便利です。
7-5. 条件に一致するデータが存在する場合だけ処理を実行する
注文一覧の中に未処理の注文がある場合だけ処理を実行する例です。
C#public class Order
{
public int Id { get; set; }
public string Status { get; set; } = "";
}
var orders = new List<Order>
{
new Order { Id = 1, Status = "完了" },
new Order { Id = 2, Status = "未処理" },
new Order { Id = 3, Status = "完了" }
};
if (orders.Exists(order => order.Status == "未処理"))
{
Console.WriteLine("未処理の注文があります");
}
条件が複数ある場合は、&&や||を使います。
C#bool exists = orders.Exists(order =>
order.Status == "未処理" || order.Status == "保留");
ただし、条件が長くなりすぎる場合は、メソッドに切り出すと読みやすくなります。
C#static bool NeedsProcessing(Order order)
{
return order.Status == "未処理" || order.Status == "保留";
}
bool exists = orders.Exists(NeedsProcessing);
7-6. nullチェックとExistsを組み合わせた安全な書き方
List<T>.Existsは、対象のリストがnullの場合に呼び出すとNullReferenceExceptionになります。
C#List<string>? names = null;
// names.Exists(name => name == "田中"); // 例外
安全に書くには、nullチェックを行います。
C#List<string>? names = null;
bool exists = names != null && names.Exists(name => name == "田中");
Console.WriteLine(exists); // False
null条件演算子を使う書き方もあります。
C#bool exists = names?.Exists(name => name == "田中") == true;
この書き方では、namesがnullの場合はfalseとして扱えます。
オブジェクトのプロパティがnullになる可能性がある場合も注意が必要です。
C#bool exists = users.Exists(user =>
user.Email != null &&
user.Email.Equals(targetEmail, StringComparison.OrdinalIgnoreCase));
nullの可能性がある値に対してメソッドを呼び出すと例外になるため、必要に応じてnullチェックを組み合わせましょう。
8. Existsを使うときのベストプラクティス
8-1. ファイル操作では例外処理もセットで考える
File.Existsで存在確認をしても、その後のファイル操作が必ず成功するとは限りません。
ファイルが削除される、アクセス権限がない、別プロセスが使用中、ディスクに問題があるなど、さまざまな理由で失敗する可能性があります。
そのため、ファイルを読み書きする処理では、try-catchを使って例外に対応しましょう。
C#try
{
if (File.Exists(path))
{
string text = File.ReadAllText(path);
Console.WriteLine(text);
}
}
catch (IOException ex)
{
Console.WriteLine($"ファイル操作エラー: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"権限エラー: {ex.Message}");
}
存在チェックはあくまで事前確認です。実際のファイル操作には例外処理が必要です。
8-2. 存在チェックだけに頼りすぎない
存在チェックは便利ですが、チェック後に状態が変わる可能性があります。
C#if (File.Exists(path))
{
File.Delete(path);
}
このコードでは、File.Existsがtrueでも、File.Deleteの前に別の処理がファイルを削除する可能性があります。
その場合、削除処理で例外が発生することがあります。
状況によっては、存在チェックをせずに処理を実行し、例外を適切に処理する方がよい場合もあります。
C#try
{
File.Delete(path);
}
catch (IOException ex)
{
Console.WriteLine($"削除に失敗しました: {ex.Message}");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine($"削除権限がありません: {ex.Message}");
}
存在チェックは「ユーザーにメッセージを出す」「処理を分岐する」ためには有効ですが、安全性を完全に保証するものではありません。
8-3. パスはPath.Combineで安全に組み立てる
ファイルパスやディレクトリパスを文字列連結で作ると、区切り文字のミスが起きやすくなります。
C#string path = baseDir + "\\" + fileName;
この書き方では、baseDirの末尾に\があるかどうかで結果が変わる可能性があります。
安全にパスを組み立てるには、Path.Combineを使いましょう。
C#string path = Path.Combine(baseDir, fileName);
複数階層のパスも簡単に組み立てられます。
C#string path = Path.Combine(baseDir, "logs", "app.log");
File.ExistsやDirectory.Existsに渡すパスは、できるだけPath.Combineで作るとミスを減らせます。
8-4. List以外のコレクションではAnyを優先する
List<T>であればExistsを使えますが、配列やIEnumerable<T>では使えません。
そのため、汎用的なコードではAnyを優先すると扱いやすくなります。
C#public bool HasActiveUser(IEnumerable<User> users)
{
return users.Any(user => user.IsActive);
}
この書き方なら、呼び出し側はList<User>でも配列でも渡せます。
C#var list = new List<User>();
var array = new User[0];
HasActiveUser(list);
HasActiveUser(array);
メソッドの引数をList<T>に限定する必要がない場合は、IEnumerable<T>とAnyの組み合わせが柔軟です。
8-5. 条件式は読みやすくシンプルに書く
Existsに渡す条件式は、できるだけシンプルに書きましょう。
C#bool exists = users.Exists(user => user.IsActive);
次のように条件が長くなると、読みづらくなります。
C#bool exists = users.Exists(user =>
user.IsActive &&
user.Age >= 20 &&
user.Role == "Admin" &&
user.LastLoginDate >= DateTime.Today.AddDays(-30));
条件が複雑な場合は、意味のあるメソッドに分けると読みやすくなります。
C#static bool IsRecentActiveAdmin(User user)
{
return user.IsActive &&
user.Age >= 20 &&
user.Role == "Admin" &&
user.LastLoginDate >= DateTime.Today.AddDays(-30);
}
bool exists = users.Exists(IsRecentActiveAdmin);
コードは動くだけでなく、後から読んで意図がわかることも重要です。
8-6. 実務で使いやすいExistsの判断基準
実務でExistsを使うときは、次のように判断するとよいでしょう。
リスト内に条件を満たす要素があるかだけを知りたい場合は、List<T>.Existsが使えます。
C#bool exists = users.Exists(user => user.Id == targetId);
ファイルがあるか確認したい場合は、File.Existsを使います。
C#bool exists = File.Exists(path);
フォルダがあるか確認したい場合は、Directory.Existsを使います。
C#bool exists = Directory.Exists(path);
配列やIEnumerable<T>を扱うなら、Anyを使います。
C#bool exists = users.Any(user => user.Id == targetId);
存在チェック後にファイル操作を行うなら、例外処理もセットで考えます。
C#try
{
if (File.Exists(path))
{
string text = File.ReadAllText(path);
}
}
catch (IOException ex)
{
Console.WriteLine(ex.Message);
}
Existsは便利ですが、対象に応じて正しく使い分けることが大切です。
9. C# Existsに関するよくある質問
9-1. C#のExistsは何をするメソッドですか?
C#のExistsは、対象が存在するかどうかをboolで判定するメソッドです。
List<T>.Existsは、リスト内に条件を満たす要素があるかを調べます。
C#bool exists = users.Exists(user => user.Id == 1);
File.Existsは、指定したファイルが存在するかを調べます。
C#bool exists = File.Exists("sample.txt");
Directory.Existsは、指定したフォルダが存在するかを調べます。
C#bool exists = Directory.Exists("logs");
存在すればtrue、存在しなければfalseを返します。
9-2. ExistsとContainsの違いは何ですか?
Existsは、条件に一致する要素があるかを判定します。
C#bool exists = numbers.Exists(n => n > 10);
Containsは、指定した値そのものが含まれているかを判定します。
C#bool contains = numbers.Contains(10);
単純に特定の値が含まれているか確認するだけなら、Containsが読みやすいです。
C#var numbers = new List<int> { 1, 2, 3 };
bool result = numbers.Contains(2);
条件を指定したい場合はExistsを使います。
C#bool result = numbers.Exists(n => n % 2 == 0);
オブジェクトのプロパティを条件にする場合もExistsが向いています。
C#bool exists = users.Exists(user => user.Email == targetEmail);
9-3. ExistsとFindの違いは何ですか?
Existsは、条件に一致する要素があるかどうかをboolで返します。
C#bool exists = users.Exists(user => user.Id == 1);
Findは、条件に一致する最初の要素そのものを返します。
C#User? user = users.Find(user => user.Id == 1);
存在するかだけ知りたいならExistsを使います。
C#if (users.Exists(user => user.Id == 1))
{
Console.WriteLine("ユーザーが存在します");
}
一致したデータを使いたいならFindを使います。
C#User? user = users.Find(user => user.Id == 1);
if (user != null)
{
Console.WriteLine(user.Name);
}
9-4. File.Existsでフォルダの存在確認はできますか?
File.Existsでフォルダの存在確認はできません。
File.Existsはファイル専用です。指定したパスがフォルダの場合、存在していてもfalseを返します。
C#bool result = File.Exists("logs"); // logs がフォルダなら False
フォルダの存在確認にはDirectory.Existsを使います。
C#bool result = Directory.Exists("logs");
ファイルとフォルダを混同しないように注意しましょう。
9-5. Directory.Existsでファイルの存在確認はできますか?
Directory.Existsでファイルの存在確認はできません。
Directory.Existsはディレクトリ専用です。指定したパスがファイルの場合、存在していてもfalseを返します。
C#bool result = Directory.Exists("sample.txt"); // sample.txt がファイルなら False
ファイルの存在確認にはFile.Existsを使います。
C#bool result = File.Exists("sample.txt");
指定したパスがファイルでもフォルダでもよい場合は、両方を組み合わせます。
C#bool exists = File.Exists(path) || Directory.Exists(path);
9-6. ExistsとAnyはどちらが速いですか?
通常の開発では、ExistsとAnyの速度差を気にする必要はほとんどありません。
どちらも条件に一致する要素を見つけた時点で探索を終了します。
C#bool result1 = list.Exists(x => x.Id == targetId);
bool result2 = list.Any(x => x.Id == targetId);
List<T>に限定するならExists、配列やIEnumerable<T>にも対応したいならAnyを選ぶとよいでしょう。
パフォーマンスが問題になる場合は、ExistsかAnyかよりも、データ構造を見直す方が効果的です。
頻繁にIDの存在チェックをするなら、HashSet<T>やDictionary<TKey, TValue>の利用も検討できます。
C#var ids = new HashSet<int> { 1, 2, 3 };
bool exists = ids.Contains(2);
9-7. 配列でExistsを使うにはどうすればよいですか?
配列にはList<T>.Existsは使えません。
C#int[] numbers = { 1, 2, 3 };
// numbers.Exists(n => n == 2); // エラー
配列で存在チェックをするなら、LINQのAnyを使うのが一般的です。
C#using System.Linq;
int[] numbers = { 1, 2, 3 };
bool exists = numbers.Any(n => n == 2);
または、Array.Existsを使う方法もあります。
C#int[] numbers = { 1, 2, 3 };
bool exists = Array.Exists(numbers, n => n == 2);
リストに変換してからExistsを使うこともできますが、存在チェックのためだけに変換する必要はあまりありません。
C#bool exists = numbers.ToList().Exists(n => n == 2);
この場合は、素直にAnyまたはArray.Existsを使う方がよいでしょう。
まとめ
C#のExistsは、「存在するかどうか」を判定するための便利なメソッドです。
List<T>.Existsは、リスト内に条件を満たす要素があるかを調べるときに使います。
C#bool exists = list.Exists(item => 条件);
File.Existsは、指定したファイルが存在するかを確認するときに使います。
C#bool exists = File.Exists(path);
Directory.Existsは、指定したフォルダが存在するかを確認するときに使います。
C#bool exists = Directory.Exists(path);
同じExistsでも、対象がリスト、ファイル、フォルダで異なるため、用途に応じて使い分ける必要があります。
また、コレクションの存在チェックでは、LINQのAnyもよく使われます。ExistsはList<T>専用、AnyはIEnumerable<T>で使えるため、汎用性を重視するならAnyが便利です。
C#bool exists = items.Any(item => 条件);
ファイルやフォルダの存在チェックでは、相対パスの基準、パスの指定ミス、アクセス権限、競合状態に注意しましょう。特にファイル操作では、存在チェックだけに頼らず、例外処理もあわせて実装することが大切です。
Existsを正しく使えば、リスト内のデータ確認、ファイルの読み書き前の確認、フォルダの自動作成など、さまざまな場面で安全で読みやすいコードを書けるようになります。

