C# 完全一致の判定方法|文字列比較・正規表現・LINQでの実装例を解説

はじめに

C#で文字列を比較するとき、「指定した文字列と完全に一致しているか」を判定したい場面はよくあります。たとえば、ユーザー入力が登録済みのIDと同じか、CSV内の行が特定のキーワードと一致するか、リスト内に指定コードが存在するか、といったケースです。

「c# 完全一致」と検索する人の多くは、==EqualsContains、正規表現、LINQなどの使い分けを知りたいはずです。C#では完全一致の判定方法が複数ありますが、目的に合わないメソッドを使うと、部分一致になったり、大文字・小文字の扱いで想定外の結果になったりします。

この記事では、C#で完全一致を判定する基本的な方法から、正規表現、LINQ、大小文字を無視する比較、nullの扱い、実装時の注意点まで、コード例付きで解説します。

1. C#における「完全一致」とは

C#における完全一致とは、比較対象の文字列全体が、指定した文字列と同じであることを意味します。

たとえば、次の2つの文字列は完全一致です。

C#
string a = "apple";
string b = "apple";

一方で、次のような文字列は完全一致ではありません。

C#
string a = "apple";
string b = "apple pie";

"apple""apple pie" の一部には含まれていますが、文字列全体が同じではないため、完全一致ではなく部分一致です。

C#で完全一致を判定する場合は、基本的には == 演算子や string.Equals メソッドを使います。検索や抽出の対象が配列やListなどのコレクションであれば、LINQの AnyWhereFirstOrDefault などを組み合わせることもあります。

1-1. 完全一致・部分一致・前方一致・後方一致の違い

文字列比較には、完全一致以外にもいくつかの判定方法があります。

完全一致は、文字列全体が同じかを判定します。

C#
string text = "CSharp";
Console.WriteLine(text == "CSharp"); // True

部分一致は、指定した文字列が含まれているかを判定します。

C#
string text = "CSharp Programming";
Console.WriteLine(text.Contains("CSharp")); // True

前方一致は、指定した文字列で始まっているかを判定します。

C#
string text = "CSharp Programming";
Console.WriteLine(text.StartsWith("CSharp")); // True

後方一致は、指定した文字列で終わっているかを判定します。

C#
string text = "CSharp Programming";
Console.WriteLine(text.EndsWith("Programming")); // True

このように、ContainsStartsWithEndsWith は便利ですが、完全一致の判定とは目的が異なります。C#で完全一致をしたい場合は、文字列全体を比較する ==Equals を使うのが基本です。

1-2. 文字列の完全一致でよく使う判定パターン

C#で文字列の完全一致を判定する代表的なパターンは、次のとおりです。

C#
string input = "admin";
string expected = "admin";

if (input == expected)
{
Console.WriteLine("完全一致しました");
}

string.Equals を使う場合は、次のように書けます。

C#
string input = "admin";
string expected = "admin";

if (string.Equals(input, expected))
{
Console.WriteLine("完全一致しました");
}

大文字・小文字を無視したい場合は、StringComparison.OrdinalIgnoreCase を指定します。

C#
string input = "ADMIN";
string expected = "admin";

if (string.Equals(input, expected, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("大文字・小文字を無視して完全一致しました");
}

配列やListの中から完全一致する要素を探す場合は、LINQの Any がよく使われます。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

bool exists = names.Any(name => name == "Bob");

Console.WriteLine(exists); // True

1-3. 検索キーワード「c# 完全一致」で知りたいこと

「c# 完全一致」と検索する場合、知りたい内容は大きく分けて次のようなものです。

まず、単純な文字列比較で完全一致を判定する方法です。これは ==string.Equals を使えば実現できます。

次に、正規表現で完全一致を判定する方法です。正規表現では、^$、または \A\z を使って、文字列全体がパターンに一致しているかを確認します。

さらに、LINQを使って配列やListの中から完全一致する要素を探す方法もよく使われます。AnyWhereFirstOrDefault を使うことで、コレクション内の検索や抽出を簡潔に書けます。

また、大文字・小文字を区別するかどうか、全角・半角をどう扱うか、nullや空文字をどう処理するかも、実装時に重要なポイントです。

2. 文字列を完全一致で判定する基本方法

C#で文字列を完全一致で判定する基本方法は、主に次の2つです。

C#
a == b

または、

C#
string.Equals(a, b)

どちらも文字列全体が同じかどうかを判定できます。ただし、比較条件を明示したい場合や、nullを安全に扱いたい場合は、string.Equals の使用がおすすめです。

2-1. == 演算子で完全一致を判定する

C#では、文字列同士を == 演算子で比較できます。

C#
string str1 = "hello";
string str2 = "hello";

if (str1 == str2)
{
Console.WriteLine("完全一致です");
}
else
{
Console.WriteLine("一致しません");
}

このコードでは、str1str2 の内容が同じなので、結果は「完全一致です」になります。

文字列の場合、== は参照先が同じかどうかではなく、文字列の内容が同じかを比較します。そのため、次のような場合でも完全一致と判定されます。

C#
string str1 = "hello";
string str2 = new string(new[] { 'h', 'e', 'l', 'l', 'o' });

Console.WriteLine(str1 == str2); // True

ただし、== では比較方法を細かく指定できません。大文字・小文字を無視したい場合や、カルチャに依存しない比較を明示したい場合は、string.EqualsStringComparison を指定する方法が適しています。

2-2. string.Equalsメソッドで判定する

string.Equals メソッドを使っても、文字列の完全一致を判定できます。

C#
string str1 = "hello";
string str2 = "hello";

bool result = string.Equals(str1, str2);

Console.WriteLine(result); // True

string.Equals の利点は、比較方法を明示できることです。

C#
string str1 = "hello";
string str2 = "HELLO";

bool result = string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

この例では、StringComparison.OrdinalIgnoreCase を指定しているため、大文字・小文字を無視して完全一致を判定できます。

厳密な完全一致をしたい場合は、次のように StringComparison.Ordinal を指定すると意図が明確になります。

C#
string str1 = "hello";
string str2 = "hello";

bool result = string.Equals(str1, str2, StringComparison.Ordinal);

Console.WriteLine(result); // True

C#で完全一致の判定を書く場合、可読性と安全性を重視するなら、string.EqualsStringComparison を指定する書き方がおすすめです。

2-3. object.Equalsとの違い

Equals には、string.Equalsobject.Equals があります。

string.Equals は文字列比較に特化したメソッドです。

C#
string a = "test";
string b = "test";

Console.WriteLine(string.Equals(a, b)); // True

一方、object.Equals はオブジェクト全般を比較するメソッドです。

C#
object a = "test";
object b = "test";

Console.WriteLine(object.Equals(a, b)); // True

文字列同士の比較であれば、通常は string.Equals を使う方が意図が明確です。

また、インスタンスメソッドの Equals を使う場合は、呼び出し元がnullだと例外が発生します。

C#
string a = null;
string b = "test";

// NullReferenceException
// bool result = a.Equals(b);

nullの可能性がある場合は、静的メソッドの string.Equals を使うと安全です。

C#
string a = null;
string b = "test";

bool result = string.Equals(a, b);

Console.WriteLine(result); // False

2-4. nullを含む文字列比較の注意点

C#で完全一致を判定する際は、nullの扱いに注意が必要です。

次のコードは、input がnullの場合に例外になります。

C#
string input = null;

if (input.Equals("admin"))
{
Console.WriteLine("一致しました");
}

input がnullの可能性がある場合は、次のように書くと安全です。

C#
string input = null;

if (string.Equals(input, "admin", StringComparison.Ordinal))
{
Console.WriteLine("一致しました");
}
else
{
Console.WriteLine("一致しません");
}

また、比較対象の定数を左側に置く方法もあります。

C#
string input = null;

if ("admin".Equals(input, StringComparison.Ordinal))
{
Console.WriteLine("一致しました");
}

ただし、比較条件を明示しやすく、nullにも安全なため、実務では次の書き方が使いやすいです。

C#
bool isMatch = string.Equals(input, "admin", StringComparison.Ordinal);

null同士を比較した場合は、完全一致として true になります。

C#
string a = null;
string b = null;

Console.WriteLine(string.Equals(a, b)); // True

一方、nullと空文字は異なります。

C#
string a = null;
string b = "";

Console.WriteLine(string.Equals(a, b)); // False

3. 大文字・小文字を区別して完全一致させる方法

C#の文字列比較では、大文字・小文字を区別するかどうかが重要です。

たとえば、"abc""ABC" は同じ文字のように見えますが、通常の比較では別の文字列として扱われます。

C#
string a = "abc";
string b = "ABC";

Console.WriteLine(a == b); // False

完全一致では、どのような比較ルールを使うかを明確にしておくことが大切です。

3-1. デフォルトの文字列比較は大文字・小文字を区別する

C#の通常の文字列比較では、大文字・小文字が区別されます。

C#
string a = "CSharp";
string b = "csharp";

Console.WriteLine(a == b); // False
Console.WriteLine(string.Equals(a, b)); // False

この場合、"CSharp""csharp" は文字列全体の文字が異なるため、完全一致とは判定されません。

ログインID、商品コード、識別子、設定値など、大文字・小文字を区別すべきデータでは、この動作が適しています。

C#
string inputCode = "ABC123";
string registeredCode = "abc123";

bool result = string.Equals(inputCode, registeredCode, StringComparison.Ordinal);

Console.WriteLine(result); // False

3-2. StringComparison.Ordinalを使う方法

厳密な文字列の完全一致を行いたい場合は、StringComparison.Ordinal を指定するのがおすすめです。

C#
string a = "sample";
string b = "sample";

bool result = string.Equals(a, b, StringComparison.Ordinal);

Console.WriteLine(result); // True

Ordinal は、文字列を言語や地域のルールではなく、文字の値に基づいて比較します。ID、コード、キー、ファイル形式の判定など、文化依存の影響を受けたくない場合に向いています。

C#
string input = "USER001";
string expected = "USER001";

if (string.Equals(input, expected, StringComparison.Ordinal))
{
Console.WriteLine("完全一致です");
}

C#で完全一致を厳密に判定するなら、StringComparison.Ordinal を明示しておくと、後からコードを読んだ人にも意図が伝わりやすくなります。

3-3. StringComparison.OrdinalIgnoreCaseで大小文字を無視する方法

大文字・小文字を無視して完全一致を判定したい場合は、StringComparison.OrdinalIgnoreCase を使います。

C#
string a = "Admin";
string b = "admin";

bool result = string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

この方法では、文字列全体が同じであれば、大文字・小文字の違いだけは無視されます。

C#
string input = "CSharp";
string keyword = "csharp";

if (string.Equals(input, keyword, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("大文字・小文字を無視して完全一致しました");
}

注意点として、OrdinalIgnoreCase は部分一致ではありません。次の例では、"CSharp" が含まれていても、文字列全体が異なるため false になります。

C#
string input = "CSharp Programming";
string keyword = "csharp";

bool result = string.Equals(input, keyword, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // False

3-4. CurrentCultureやInvariantCultureとの違い

StringComparison には、Ordinal 以外にも CurrentCultureInvariantCulture があります。

CurrentCulture は、現在のカルチャ、つまり実行環境の言語や地域のルールに基づいて比較します。

C#
string.Equals(a, b, StringComparison.CurrentCulture);

InvariantCulture は、特定の地域に依存しないカルチャルールで比較します。

C#
string.Equals(a, b, StringComparison.InvariantCulture);

一方、Ordinal は言語的な意味ではなく、文字そのものの値で比較します。

C#
string.Equals(a, b, StringComparison.Ordinal);

ユーザーに表示される自然言語の並び替えや検索では、カルチャを考慮した比較が必要になることがあります。しかし、ID、コード、キー、ファイル名、設定値などを完全一致で判定する場合は、Ordinal または OrdinalIgnoreCase が適していることが多いです。

4. 正規表現で完全一致を判定する方法

C#では、正規表現を使って完全一致を判定することもできます。

正規表現は、単純な文字列比較ではなく、「英数字のみ」「数字3桁」「特定の形式のコード」など、パターンを指定して一致判定したい場合に便利です。

ただし、固定文字列が完全一致するかを判定するだけなら、正規表現より string.Equals の方がシンプルで高速です。正規表現は、パターン判定が必要な場合に使うのが基本です。

4-1. Regex.IsMatchの基本構文

C#で正規表現を使うには、System.Text.RegularExpressions 名前空間の Regex クラスを使います。

C#
using System.Text.RegularExpressions;

string input = "abc123";

bool result = Regex.IsMatch(input, @"abc123");

Console.WriteLine(result); // True

ただし、この書き方では完全一致ではなく、部分一致として判定されます。

C#
using System.Text.RegularExpressions;

string input = "xxxabc123yyy";

bool result = Regex.IsMatch(input, @"abc123");

Console.WriteLine(result); // True

"abc123" が文字列の一部に含まれているため、true になります。正規表現で完全一致を判定したい場合は、文字列の先頭と末尾を指定する必要があります。

4-2. ^ と $ を使って完全一致させる

正規表現でよく使われる完全一致の書き方は、^$ を使う方法です。

C#
using System.Text.RegularExpressions;

string input = "abc123";

bool result = Regex.IsMatch(input, @"^abc123$");

Console.WriteLine(result); // True

^ は文字列の先頭、$ は文字列の末尾を表します。そのため、^abc123$ は「文字列全体が abc123 であること」を意味します。

次のように前後に別の文字がある場合は一致しません。

C#
using System.Text.RegularExpressions;

string input = "xxxabc123yyy";

bool result = Regex.IsMatch(input, @"^abc123$");

Console.WriteLine(result); // False

入力値が特定形式に完全一致するかを調べる場合にも使えます。

C#
using System.Text.RegularExpressions;

string input = "A123";

bool result = Regex.IsMatch(input, @"^[A-Z][0-9]{3}$");

Console.WriteLine(result); // True

この例では、「大文字アルファベット1文字 + 数字3桁」に完全一致するかを判定しています。

4-3. \A と \z を使った厳密な完全一致

正規表現でより厳密に文字列全体の完全一致を判定したい場合は、\A\z を使います。

C#
using System.Text.RegularExpressions;

string input = "abc123";

bool result = Regex.IsMatch(input, @"\Aabc123\z");

Console.WriteLine(result); // True

\A は入力文字列の先頭、\z は入力文字列の末尾を表します。

^$ も先頭・末尾を表しますが、オプションや改行の扱いによって挙動が変わることがあります。特に複数行の入力を扱う場合や、末尾の改行まで厳密に判定したい場合は、\A\z を使う方が意図が明確です。

C#
using System.Text.RegularExpressions;

string input = "abc123\n";

bool result1 = Regex.IsMatch(input, @"^abc123$");
bool result2 = Regex.IsMatch(input, @"\Aabc123\z");

Console.WriteLine(result1);
Console.WriteLine(result2);

改行を含む入力では、アンカーの選び方によって結果が変わる可能性があります。厳密な完全一致を求める場合は、\A...\z の形を覚えておくとよいでしょう。

4-4. RegexOptions.IgnoreCaseで大文字・小文字を無視する

正規表現で大文字・小文字を無視して完全一致させたい場合は、RegexOptions.IgnoreCase を指定します。

C#
using System.Text.RegularExpressions;

string input = "ABC123";

bool result = Regex.IsMatch(input, @"\Aabc123\z", RegexOptions.IgnoreCase);

Console.WriteLine(result); // True

パターンを使った入力チェックでも同じように指定できます。

C#
using System.Text.RegularExpressions;

string input = "a123";

bool result = Regex.IsMatch(input, @"\A[A-Z][0-9]{3}\z", RegexOptions.IgnoreCase);

Console.WriteLine(result); // True

ただし、固定文字列の大文字・小文字を無視した完全一致であれば、正規表現よりも次のように string.Equals を使う方がシンプルです。

C#
string input = "ABC123";
string expected = "abc123";

bool result = string.Equals(input, expected, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

4-5. 特殊文字を含む文字列はRegex.Escapeでエスケープする

正規表現では、.+*?()[] などは特別な意味を持ちます。そのため、これらの文字を普通の文字として完全一致させたい場合は、エスケープが必要です。

たとえば、"C#""a+b" のような文字列を正規表現で扱う場合は、Regex.Escape を使うと安全です。

C#
using System.Text.RegularExpressions;

string input = "a+b";
string keyword = "a+b";

string pattern = @"\A" + Regex.Escape(keyword) + @"\z";

bool result = Regex.IsMatch(input, pattern);

Console.WriteLine(result); // True

Regex.Escape を使わずに "a+b" を正規表現として扱うと、+ が「直前の文字の1回以上の繰り返し」という意味になってしまいます。

C#
using System.Text.RegularExpressions;

string input = "aaab";
string pattern = @"\Aa+b\z";

bool result = Regex.IsMatch(input, pattern);

Console.WriteLine(result); // True

固定文字列を正規表現で完全一致させる場合は、Regex.Escape を使うことをおすすめします。

5. LINQで完全一致を判定する方法

配列やListなどのコレクション内に、指定した文字列と完全一致する要素があるかを調べる場合は、LINQが便利です。

LINQを使うと、検索、抽出、最初の一致要素の取得などを簡潔に書けます。

5-1. 配列やList内に完全一致する文字列があるか判定する

配列の中に完全一致する文字列があるかを判定する例です。

C#
string[] fruits = { "apple", "banana", "orange" };

bool exists = fruits.Contains("banana");

Console.WriteLine(exists); // True

この場合の Contains は、文字列の Contains ではなく、コレクションに対するLINQの Contains です。要素全体が一致するかを判定します。

文字列の Contains は部分一致ですが、配列やListに対する Contains は、要素として完全一致するものがあるかを確認します。

C#
string[] words = { "apple", "banana", "orange" };

Console.WriteLine(words.Contains("app")); // False
Console.WriteLine(words.Contains("apple")); // True

5-2. Anyを使った完全一致検索

LINQの Any を使うと、条件に一致する要素が1つでも存在するかを判定できます。

C#
var users = new List<string> { "admin", "user", "guest" };

bool exists = users.Any(user => user == "admin");

Console.WriteLine(exists); // True

string.Equals を使うと、比較条件を明示できます。

C#
var users = new List<string> { "admin", "user", "guest" };

bool exists = users.Any(user =>
string.Equals(user, "admin", StringComparison.Ordinal));

Console.WriteLine(exists); // True

大文字・小文字を無視したい場合は、OrdinalIgnoreCase を指定します。

C#
var users = new List<string> { "Admin", "User", "Guest" };

bool exists = users.Any(user =>
string.Equals(user, "admin", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(exists); // True

5-3. Whereで完全一致する要素を抽出する

完全一致する要素をすべて取得したい場合は、Where を使います。

C#
var codes = new List<string>
{
"A001",
"B002",
"A001",
"C003"
};

var matches = codes.Where(code => code == "A001");

foreach (var match in matches)
{
Console.WriteLine(match);
}

結果は次のようになります。

A001
A001

string.Equals を使って比較方法を明示することもできます。

C#
var matches = codes.Where(code =>
string.Equals(code, "A001", StringComparison.Ordinal));

大文字・小文字を無視する場合は、次のようにします。

C#
var codes = new List<string> { "a001", "A001", "B002" };

var matches = codes.Where(code =>
string.Equals(code, "A001", StringComparison.OrdinalIgnoreCase));

foreach (var match in matches)
{
Console.WriteLine(match);
}

5-4. FirstOrDefaultで最初に一致する要素を取得する

完全一致する最初の要素を取得したい場合は、FirstOrDefault を使います。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

string result = names.FirstOrDefault(name => name == "Bob");

Console.WriteLine(result); // Bob

一致する要素がない場合は、参照型であれば null が返ります。

C#
var names = new List<string> { "Alice", "Bob", "Charlie" };

string result = names.FirstOrDefault(name => name == "David");

Console.WriteLine(result == null); // True

FirstOrDefault でも、string.Equals を使って比較条件を指定できます。

C#
string result = names.FirstOrDefault(name =>
string.Equals(name, "bob", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(result); // Bob

完全一致する要素が存在するかだけ知りたい場合は Any、要素を取得したい場合は FirstOrDefault を使うとよいでしょう。

5-5. SequenceEqualでコレクション全体の完全一致を判定する

コレクション全体が完全一致しているかを判定する場合は、SequenceEqual を使います。

C#
var list1 = new List<string> { "A", "B", "C" };
var list2 = new List<string> { "A", "B", "C" };

bool result = list1.SequenceEqual(list2);

Console.WriteLine(result); // True

SequenceEqual は、要素数、要素の順序、各要素の値がすべて一致している場合に true を返します。

順序が違う場合は、同じ要素を含んでいても完全一致にはなりません。

C#
var list1 = new List<string> { "A", "B", "C" };
var list2 = new List<string> { "C", "B", "A" };

bool result = list1.SequenceEqual(list2);

Console.WriteLine(result); // False

大文字・小文字を無視して比較したい場合は、比較子を指定します。

C#
var list1 = new List<string> { "A", "B", "C" };
var list2 = new List<string> { "a", "b", "c" };

bool result = list1.SequenceEqual(list2, StringComparer.OrdinalIgnoreCase);

Console.WriteLine(result); // True

6. 完全一致と間違えやすいメソッド

C#で完全一致を判定するつもりで、誤って部分一致や前方一致のメソッドを使ってしまうケースがあります。

特に ContainsStartsWithEndsWithIndexOf は便利ですが、完全一致の判定とは異なります。

6-1. Containsは部分一致の判定

文字列に対する Contains は、指定した文字列が含まれているかを判定します。

C#
string text = "CSharp Programming";

bool result = text.Contains("CSharp");

Console.WriteLine(result); // True

しかし、これは完全一致ではありません。

C#
string text = "CSharp Programming";

bool result = text.Contains("CSharp");

Console.WriteLine(result); // True

text"CSharp" と完全一致しているわけではありません。あくまで "CSharp" を含んでいるだけです。

完全一致を判定したい場合は、次のように書きます。

C#
string text = "CSharp Programming";

bool result = string.Equals(text, "CSharp", StringComparison.Ordinal);

Console.WriteLine(result); // False

6-2. StartsWithは前方一致の判定

StartsWith は、文字列が指定した文字列で始まるかを判定します。

C#
string text = "CSharp Programming";

bool result = text.StartsWith("CSharp");

Console.WriteLine(result); // True

この結果は true ですが、完全一致ではありません。"CSharp Programming""CSharp" で始まっているだけです。

完全一致を判定するなら、次のようにします。

C#
string text = "CSharp Programming";

bool result = string.Equals(text, "CSharp", StringComparison.Ordinal);

Console.WriteLine(result); // False

6-3. EndsWithは後方一致の判定

EndsWith は、文字列が指定した文字列で終わるかを判定します。

C#
string fileName = "report.csv";

bool result = fileName.EndsWith(".csv");

Console.WriteLine(result); // True

これは拡張子の判定などには便利ですが、完全一致ではありません。

完全一致でファイル名全体を比較したい場合は、次のようにします。

C#
string fileName = "report.csv";

bool result = string.Equals(fileName, "report.csv", StringComparison.Ordinal);

Console.WriteLine(result); // True

6-4. IndexOfは完全一致ではなく位置検索

IndexOf は、指定した文字列が最初に出現する位置を返すメソッドです。

C#
string text = "CSharp Programming";

int index = text.IndexOf("Sharp");

Console.WriteLine(index); // 1

見つからない場合は -1 が返ります。

C#
string text = "CSharp Programming";

int index = text.IndexOf("Java");

Console.WriteLine(index); // -1

IndexOf を使って次のように書くと、部分一致の判定になります。

C#
string text = "CSharp Programming";

bool result = text.IndexOf("CSharp") >= 0;

Console.WriteLine(result); // True

完全一致をしたい場合は、IndexOf ではなく string.Equals を使いましょう。

C#
bool result = string.Equals(text, "CSharp", StringComparison.Ordinal);

6-5. TrimやNormalizeが必要になるケース

見た目では同じ文字列に見えても、前後に空白が含まれていると完全一致しません。

C#
string input = "admin ";
string expected = "admin";

bool result = string.Equals(input, expected, StringComparison.Ordinal);

Console.WriteLine(result); // False

前後の空白を無視したい場合は、Trim を使います。

C#
string input = "admin ";
string expected = "admin";

bool result = string.Equals(input.Trim(), expected, StringComparison.Ordinal);

Console.WriteLine(result); // True

ただし、Trim を使うと、本来区別すべき空白まで取り除いてしまう可能性があります。パスワードやコードなど、空白も意味を持つデータでは注意が必要です。

また、Unicodeの正規化形式が異なると、見た目が同じでも一致しないことがあります。このような場合は Normalize を使います。

C#
string a = "é";
string b = "e\u0301";

bool result1 = string.Equals(a, b, StringComparison.Ordinal);
bool result2 = string.Equals(a.Normalize(), b.Normalize(), StringComparison.Ordinal);

Console.WriteLine(result1); // Falseの場合がある
Console.WriteLine(result2); // True

ユーザー入力を扱う場合は、空白、改行、全角・半角、正規化の必要性を事前に検討することが重要です。

7. 実装例で比較するC#の完全一致判定

ここでは、C#で完全一致を判定する具体的な実装例を紹介します。単純な文字列比較、ファイル検索、リスト検索、正規表現、LINQの複数条件など、実務で使いやすい形で確認していきます。

7-1. ユーザー入力と登録済み文字列を比較する例

ユーザーが入力したユーザー名と、登録済みのユーザー名を完全一致で比較する例です。

C#
using System;

class Program
{
static void Main()
{
string registeredUserName = "admin";

Console.Write("ユーザー名を入力してください: ");
string input = Console.ReadLine();

if (string.Equals(input, registeredUserName, StringComparison.Ordinal))
{
Console.WriteLine("ユーザー名が一致しました");
}
else
{
Console.WriteLine("ユーザー名が一致しません");
}
}
}

大文字・小文字を無視したい場合は、次のようにします。

C#
if (string.Equals(input, registeredUserName, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("ユーザー名が一致しました");
}

ただし、ログインIDやパスワードのように厳密性が必要な情報では、大文字・小文字を区別するかどうかを慎重に決める必要があります。

7-2. CSVやテキストファイルの行を完全一致で検索する例

テキストファイルの各行から、指定した文字列と完全一致する行を探す例です。

C#
using System;
using System.IO;
using System.Linq;

class Program
{
static void Main()
{
string path = "data.txt";
string keyword = "ERROR";

bool exists = File.ReadLines(path)
.Any(line => string.Equals(line, keyword, StringComparison.Ordinal));

if (exists)
{
Console.WriteLine("完全一致する行が見つかりました");
}
else
{
Console.WriteLine("完全一致する行はありません");
}
}
}

前後の空白を無視したい場合は、Trim を使います。

C#
bool exists = File.ReadLines(path)
.Any(line => string.Equals(line.Trim(), keyword, StringComparison.Ordinal));

ただし、CSVの場合は単純に行全体を比較するのではなく、カラム単位で比較することが多いです。

C#
using System;
using System.IO;
using System.Linq;

class Program
{
static void Main()
{
string path = "users.csv";
string targetId = "U001";

bool exists = File.ReadLines(path)
.Select(line => line.Split(','))
.Any(columns => columns.Length > 0 &&
string.Equals(columns[0], targetId, StringComparison.Ordinal));

Console.WriteLine(exists);
}
}

この例では、CSVの1列目が指定IDと完全一致するかを判定しています。

7-3. リスト内のIDやコードを完全一致で探す例

リスト内から、指定したIDやコードを完全一致で探す例です。

C#
using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
static void Main()
{
var productCodes = new List<string>
{
"P001",
"P002",
"P003"
};

string targetCode = "P002";

bool exists = productCodes.Any(code =>
string.Equals(code, targetCode, StringComparison.Ordinal));

Console.WriteLine(exists); // True
}
}

商品コード、会員ID、注文番号などは、部分一致ではなく完全一致で判定するのが基本です。

C#
string targetCode = "P00";

bool exists = productCodes.Any(code =>
string.Equals(code, targetCode, StringComparison.Ordinal));

Console.WriteLine(exists); // False

"P001""P002""P00" は含まれていますが、完全一致ではないため false になります。

7-4. 正規表現で入力値を完全一致チェックする例

入力値が「英大文字1文字 + 数字4桁」の形式に完全一致するかを判定する例です。

C#
using System;
using System.Text.RegularExpressions;

class Program
{
static void Main()
{
string input = "A1234";

bool isValid = Regex.IsMatch(input, @"\A[A-Z][0-9]{4}\z");

Console.WriteLine(isValid); // True
}
}

次の入力は一致しません。

C#
string input = "A12345";

bool isValid = Regex.IsMatch(input, @"\A[A-Z][0-9]{4}\z");

Console.WriteLine(isValid); // False

数字のみの完全一致チェックであれば、次のように書けます。

C#
string input = "123456";

bool isNumber = Regex.IsMatch(input, @"\A[0-9]+\z");

Console.WriteLine(isNumber); // True

メールアドレスや郵便番号、商品コードなど、特定の形式を判定する場合は、正規表現による完全一致が役立ちます。

7-5. LINQで複数条件を組み合わせる例

LINQでは、完全一致に加えて複数条件を組み合わせることもできます。

C#
using System;
using System.Collections.Generic;
using System.Linq;

class User
{
public string Id { get; set; }
public string Status { get; set; }
}

class Program
{
static void Main()
{
var users = new List<User>
{
new User { Id = "U001", Status = "Active" },
new User { Id = "U002", Status = "Inactive" },
new User { Id = "U003", Status = "Active" }
};

string targetId = "U001";

bool exists = users.Any(user =>
string.Equals(user.Id, targetId, StringComparison.Ordinal) &&
string.Equals(user.Status, "Active", StringComparison.Ordinal));

Console.WriteLine(exists); // True
}
}

完全一致するユーザーを取得したい場合は、FirstOrDefault を使います。

C#
User user = users.FirstOrDefault(user =>
string.Equals(user.Id, targetId, StringComparison.Ordinal) &&
string.Equals(user.Status, "Active", StringComparison.Ordinal));

if (user != null)
{
Console.WriteLine($"一致したユーザーID: {user.Id}");
}

複数条件を組み合わせる場合でも、文字列比較には string.EqualsStringComparison を指定しておくと、意図しない比較を避けやすくなります。

8. 完全一致判定で注意すべきポイント

C#で完全一致を判定するときは、単に ==Equals を使うだけでは不十分な場合があります。null、空文字、空白、全角・半角、改行コード、カルチャ、パフォーマンスなどを考慮することで、より安全で意図通りの実装になります。

8-1. null・空文字・空白文字の扱い

null、空文字、空白文字はそれぞれ異なります。

C#
string a = null;
string b = "";
string c = " ";

Console.WriteLine(string.Equals(a, b)); // False
Console.WriteLine(string.Equals(b, c)); // False

空文字は長さ0の文字列ですが、nullは文字列オブジェクトが存在しない状態です。空白文字は見た目では分かりにくいですが、文字として存在します。

入力値が未入力かどうかを判定したい場合は、string.IsNullOrEmptystring.IsNullOrWhiteSpace を使います。

C#
string input = " ";

Console.WriteLine(string.IsNullOrEmpty(input)); // False
Console.WriteLine(string.IsNullOrWhiteSpace(input)); // True

完全一致の前に空白だけの入力を無効にしたい場合は、次のように書けます。

C#
if (!string.IsNullOrWhiteSpace(input) &&
string.Equals(input, "admin", StringComparison.Ordinal))
{
Console.WriteLine("完全一致しました");
}

8-2. 全角・半角の違い

C#の通常の完全一致では、全角と半角は別の文字として扱われます。

C#
string a = "ABC";
string b = "ABC";

bool result = string.Equals(a, b, StringComparison.Ordinal);

Console.WriteLine(result); // False

数字でも同じです。

C#
string a = "123";
string b = "123";

bool result = string.Equals(a, b, StringComparison.Ordinal);

Console.WriteLine(result); // False

ユーザー入力で全角・半角の揺れを吸収したい場合は、事前に変換や正規化を行う必要があります。ただし、全角・半角を同一視してよいかは業務要件によります。

たとえば、コードやIDでは全角・半角を区別すべき場合があります。一方、検索キーワードや名前入力では、ある程度揺れを吸収した方が使いやすい場合もあります。

8-3. 改行コードや不可視文字による不一致

見た目では同じ文字列に見えても、改行コードやタブなどの不可視文字が含まれていると完全一致しません。

C#
string a = "admin";
string b = "admin\n";

bool result = string.Equals(a, b, StringComparison.Ordinal);

Console.WriteLine(result); // False

Windowsの改行コード \r\n、Unix系の改行コード \n、タブ \t なども不一致の原因になります。

C#
string input = "admin\t";
string expected = "admin";

bool result = string.Equals(input, expected, StringComparison.Ordinal);

Console.WriteLine(result); // False

前後の空白や改行を無視したい場合は、Trim を使えます。

C#
bool result = string.Equals(input.Trim(), expected, StringComparison.Ordinal);

ただし、文字列の途中に含まれる空白やタブは Trim では削除されません。必要に応じて、置換や正規表現による整形を検討します。

8-4. 文化依存の比較による想定外の結果

文字列比較では、カルチャによって結果が変わる可能性があります。特に、自然言語の比較では、言語ごとの大文字・小文字、アクセント、記号の扱いが関係することがあります。

ID、コード、キー、設定値などを比較する場合は、文化依存の比較ではなく、StringComparison.Ordinal を指定するのが安全です。

C#
bool result = string.Equals(input, expected, StringComparison.Ordinal);

大文字・小文字を無視したい場合も、コードや識別子では OrdinalIgnoreCase が適しています。

C#
bool result = string.Equals(input, expected, StringComparison.OrdinalIgnoreCase);

自然言語としての検索や表示順を扱う場合は CurrentCulture などが必要になることもありますが、完全一致の厳密性を重視する場面では、まず Ordinal を検討するとよいでしょう。

8-5. パフォーマンスを意識した比較方法の選び方

単純な完全一致であれば、string.Equals== が最もシンプルです。正規表現は強力ですが、固定文字列の一致判定だけに使うと過剰な実装になることがあります。

たとえば、次のような固定文字列の比較では、正規表現より string.Equals が適しています。

C#
bool result = string.Equals(input, "admin", StringComparison.Ordinal);

一方、入力形式のチェックでは正規表現が便利です。

C#
bool result = Regex.IsMatch(input, @"\A[A-Z][0-9]{4}\z");

大量データから完全一致を何度も検索する場合は、ListよりもHashSetを使う方が効率的なことがあります。

C#
var codes = new HashSet<string>(StringComparer.Ordinal)
{
"A001",
"B002",
"C003"
};

bool exists = codes.Contains("B002");

Console.WriteLine(exists); // True

大文字・小文字を無視する場合は、HashSet作成時に比較子を指定します。

C#
var codes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"A001",
"B002",
"C003"
};

bool exists = codes.Contains("b002");

Console.WriteLine(exists); // True

9. 目的別のおすすめ実装方法

C#で完全一致を判定する方法は複数あります。どれを使うべきかは、目的によって変わります。

単純な文字列比較であれば string.Equals、大小文字を無視したいなら OrdinalIgnoreCase、パターンを使いたいなら正規表現、コレクション検索ならLINQやHashSetを使うとよいでしょう。

9-1. 単純な文字列比較ならstring.Equals

単純に2つの文字列が完全一致するかを判定するなら、string.Equals がおすすめです。

C#
bool result = string.Equals(input, expected, StringComparison.Ordinal);

この書き方は、nullに安全で、比較方法も明示できます。

== でも完全一致は判定できますが、比較ルールを明確にしたい場合は string.Equals の方が読みやすくなります。

C#
if (string.Equals(input, "OK", StringComparison.Ordinal))
{
Console.WriteLine("OKです");
}

9-2. 大文字・小文字を無視するならStringComparison.OrdinalIgnoreCase

大文字・小文字を無視して完全一致させたい場合は、StringComparison.OrdinalIgnoreCase を使います。

C#
bool result = string.Equals(input, expected, StringComparison.OrdinalIgnoreCase);

たとえば、コマンド入力や拡張子の判定などで使えます。

C#
string extension = ".CSV";

bool isCsv = string.Equals(extension, ".csv", StringComparison.OrdinalIgnoreCase);

Console.WriteLine(isCsv); // True

ただし、大文字・小文字を区別すべきデータでは使わないようにしましょう。

9-3. パターンを含めたいなら正規表現

完全一致に加えて、形式のチェックも行いたい場合は正規表現が適しています。

C#
bool result = Regex.IsMatch(input, @"\A[0-9]{3}-[0-9]{4}\z");

この例では、郵便番号のような「数字3桁-数字4桁」の形式に完全一致するかを判定しています。

固定文字列ではなく、文字種や桁数、繰り返しなどを指定したい場合は、正規表現を使うと簡潔に書けます。

C#
bool isCode = Regex.IsMatch(input, @"\A[A-Z]{2}[0-9]{5}\z");

9-4. コレクション検索ならLINQ

配列やListから完全一致する要素を探すなら、LINQが便利です。

存在確認なら Any を使います。

C#
bool exists = list.Any(x =>
string.Equals(x, target, StringComparison.Ordinal));

一致する要素を抽出するなら Where を使います。

C#
var matches = list.Where(x =>
string.Equals(x, target, StringComparison.Ordinal));

最初の一致要素を取得するなら FirstOrDefault を使います。

C#
var match = list.FirstOrDefault(x =>
string.Equals(x, target, StringComparison.Ordinal));

大量データに対して何度も検索する場合は、LINQよりHashSetの利用も検討するとよいでしょう。

9-5. 厳密性と速度を重視するならOrdinal比較

厳密性と速度を重視するなら、StringComparison.Ordinal を指定した比較がおすすめです。

C#
bool result = string.Equals(input, expected, StringComparison.Ordinal);

大文字・小文字を無視する必要がある場合は、StringComparison.OrdinalIgnoreCase を使います。

C#
bool result = string.Equals(input, expected, StringComparison.OrdinalIgnoreCase);

ID、コード、キー、ファイル名、設定値など、プログラム内部で扱う文字列の完全一致には、Ordinal比較が向いています。

10. C#の完全一致に関するよくある質問

C#で完全一致を判定するときによくある疑問をまとめます。

10-1. == と Equals はどちらを使うべきか

どちらでも文字列の完全一致は判定できます。

C#
string a = "test";
string b = "test";

Console.WriteLine(a == b); // True
Console.WriteLine(string.Equals(a, b)); // True

ただし、実務では string.EqualsStringComparison を指定する書き方がおすすめです。

C#
bool result = string.Equals(a, b, StringComparison.Ordinal);

理由は、比較方法が明確になり、nullにも安全だからです。特に、C#で完全一致の判定を明示したい場合は、StringComparison.Ordinal または StringComparison.OrdinalIgnoreCase を指定するとよいでしょう。

10-2. Containsで完全一致は判定できるか

文字列の Contains は完全一致ではなく、部分一致の判定です。

C#
string text = "abcdef";

Console.WriteLine(text.Contains("abc")); // True

この場合、"abc" は含まれていますが、text 全体が "abc" と一致しているわけではありません。

完全一致を判定する場合は、次のようにします。

C#
bool result = string.Equals(text, "abc", StringComparison.Ordinal);

ただし、配列やListに対する Contains は、要素として完全一致するものがあるかを判定します。

C#
var list = new List<string> { "abc", "def" };

Console.WriteLine(list.Contains("abc")); // True
Console.WriteLine(list.Contains("a")); // False

文字列の Contains と、コレクションの Contains は意味が異なるため注意しましょう。

10-3. 正規表現の ^$ と \A\z の違いは何か

^$ は、正規表現で先頭と末尾を表すアンカーです。

C#
Regex.IsMatch(input, @"^abc$")

一方、\A\z は、入力文字列全体の先頭と末尾をより厳密に表します。

C#
Regex.IsMatch(input, @"\Aabc\z")

通常の単一行文字列では、どちらも完全一致のように使えます。しかし、複数行モードや末尾の改行を扱う場合に挙動が変わることがあるため、厳密な完全一致を意図するなら \A...\z を使うのがおすすめです。

10-4. 大文字・小文字を無視して完全一致させるにはどうするか

string.EqualsStringComparison.OrdinalIgnoreCase を指定します。

C#
string a = "CSharp";
string b = "csharp";

bool result = string.Equals(a, b, StringComparison.OrdinalIgnoreCase);

Console.WriteLine(result); // True

LINQで使う場合も同じです。

C#
var list = new List<string> { "CSharp", "Java", "Python" };

bool exists = list.Any(x =>
string.Equals(x, "csharp", StringComparison.OrdinalIgnoreCase));

Console.WriteLine(exists); // True

正規表現の場合は、RegexOptions.IgnoreCase を指定します。

C#
bool result = Regex.IsMatch(input, @"\Acsharp\z", RegexOptions.IgnoreCase);

10-5. LINQで完全一致する要素が存在するか確認するにはどうするか

LINQで完全一致する要素が存在するか確認するには、Any を使います。

C#
var list = new List<string> { "A001", "B002", "C003" };

bool exists = list.Any(x =>
string.Equals(x, "B002", StringComparison.Ordinal));

Console.WriteLine(exists); // True

大文字・小文字を無視する場合は、次のようにします。

C#
bool exists = list.Any(x =>
string.Equals(x, "b002", StringComparison.OrdinalIgnoreCase));

単純に要素の完全一致を確認するだけなら、コレクションの Contains も使えます。

C#
bool exists = list.Contains("B002");

ただし、比較方法を明示したい場合は、Anystring.Equals を組み合わせる方が柔軟です。

まとめ

C#で完全一致を判定する基本は、== 演算子または string.Equals を使った文字列比較です。特に実務では、比較方法を明示できる string.Equals(input, expected, StringComparison.Ordinal) のような書き方が安全で分かりやすいです。

大文字・小文字を区別するなら StringComparison.Ordinal、大文字・小文字を無視するなら StringComparison.OrdinalIgnoreCase を使います。ID、コード、キー、設定値などの厳密な比較では、カルチャに依存しないOrdinal比較が適しています。

正規表現で完全一致を判定する場合は、^...$ または \A...\z を使います。より厳密に文字列全体を判定したい場合は、\A\z を使うと意図が明確です。また、固定文字列を正規表現に埋め込む場合は、Regex.Escape で特殊文字をエスケープしましょう。

配列やListなどのコレクション内で完全一致を検索する場合は、LINQの AnyWhereFirstOrDefault が便利です。コレクション全体の完全一致を判定したい場合は、SequenceEqual を使います。

一方、ContainsStartsWithEndsWithIndexOf は完全一致ではなく、部分一致・前方一致・後方一致・位置検索のためのメソッドです。C#で完全一致を実装する際は、目的に合ったメソッドを選び、null、空文字、空白、全角・半角、改行コード、カルチャの違いにも注意しましょう。