C#でアプリケーションを開発する際、文字列の比較は避けて通れない非常に重要な処理の一つです。
ユーザー入力の検証、リストの並べ替え、特定のキーワードの検索など、多くの場面で文字列同士を比べる必要があります。
C#には比較演算子である==やEqualsメソッドがありますが、より詳細な制御が必要な場合に重宝するのがString.Compareメソッドです。
この記事では、String.Compareの基本的な使い方から、実務で欠かせない大文字小文字の区別、カルチャ(言語)を考慮した比較方法までを徹底的に解説します。
String.Compareの基本概念と戻り値の仕組み
String.Compareは、2つの文字列を比較して、それらの相対的な順序を示す整数値を返す静的メソッドです。
単に「一致するかどうか」を知るだけでなく、「どちらの文字列が辞書順で先に来るか」を判定できるのが最大の特徴です。

String.Compareの戻り値は、単純な真偽値(bool)ではなくint型の数値で返されます。
この数値の意味を正しく理解することが、このメソッドを使いこなす第一歩となります。
| 戻り値 | 意味 |
|---|---|
| 0より小さい値 (負の整数) | 1番目の文字列が、2番目の文字列よりも前に位置する。 |
| 0 | 2つの文字列が等しい。 |
| 0より大きい値 (正の整数) | 1番目の文字列が、2番目の文字列よりも後に位置する。 |
一般的に、戻り値には-1、0、1が使われることが多いですが、仕様上は「0より小さいか大きいか」で判断するのが正しい作法です。
基本的な使い方のサンプルコード
まずは、最もシンプルな2つの引数を取るString.Compareの挙動を確認してみましょう。
using System;
class Program
{
static void Main()
{
string strA = "apple";
string strB = "banana";
string strC = "apple";
// apple と banana を比較 (appleが先なので負の値)
int result1 = String.Compare(strA, strB);
Console.WriteLine($"比較1: {strA} vs {strB} = {result1}");
// apple と apple を比較 (一致するので 0)
int result2 = String.Compare(strA, strC);
Console.WriteLine($"比較2: {strA} vs {strC} = {result2}");
// banana と apple を比較 (bananaが後なので正の値)
int result3 = String.Compare(strB, strA);
Console.WriteLine($"比較3: {strB} vs {strA} = {result3}");
}
}
比較1: apple vs banana = -1
比較2: apple vs apple = 0
比較3: banana vs apple = 1
このように、辞書順での並び替えを前提としたプログラムでは、この数値を利用して要素をソートすることができます。
大文字と小文字を区別しない比較方法
実務において頻繁に発生するのが、「大文字と小文字を区別せずに比較したい」というケースです。
例えば、ログインIDのチェックや検索キーワードの照合などがこれに当たります。

String.Compareには、第3引数にbool ignoreCaseを指定できるオーバーロードが存在します。
ここにtrueを渡すことで、簡単に大文字小文字を無視した比較が可能です。
ignoreCaseパラメータを利用した例
using System;
class Program
{
static void Main()
{
string upper = "HELLO";
string lower = "hello";
// デフォルト(第3引数なし)は区別する
int sensitive = String.Compare(upper, lower);
Console.WriteLine($"区別あり: {sensitive} (0ではないため一致しない)");
// 第3引数に true を渡すと区別しない
int insensitive = String.Compare(upper, lower, true);
Console.WriteLine($"区別なし: {insensitive} (0なので一致とみなす)");
}
}
区別あり: 1 (0ではないため一致しない)
区別なし: 0 (0なので一致とみなす)
この方法は非常にシンプルですが、現在のC#開発(特に.NET Core以降)では、より詳細な挙動を制御できるStringComparison列挙型を使用することが推奨されています。
StringComparison列挙型による高度な比較
StringComparison列挙型を使用すると、大文字小文字の区別だけでなく、「カルチャ(言語規則)」をどのように扱うかも指定できます。
これにより、実行環境に左右されない安定したコードを書くことができます。

主要なStringComparisonの値は以下の通りです。
- Ordinal
各文字のバイナリ値を使用して比較します。
最もパフォーマンスが高く、プログラム内部の識別子比較などに適しています。
- OrdinalIgnoreCase
バイナリ比較を行いながら、大文字小文字を区別しません。
- CurrentCulture
実行中のスレッドのカルチャ設定(OSの言語設定など)を使用して比較します。
ユーザーに表示するリストのソートなどに適しています。
- InvariantCulture
特定の言語に依存しない「不変なカルチャ」を使用して比較します。
設定ファイルなどの保存、読み込みに適しています。
StringComparisonを使用したコード例
using System;
class Program
{
static void Main()
{
string a = "apple";
string b = "APPLE";
// 順序比較(大文字小文字を区別しない)で最も一般的な方法
if (String.Compare(a, b, StringComparison.OrdinalIgnoreCase) == 0)
{
Console.WriteLine("OrdinalIgnoreCase: 一致しています。");
}
// 順序比較(大文字小文字を区別する)
if (String.Compare(a, b, StringComparison.Ordinal) != 0)
{
Console.WriteLine("Ordinal: 一致していません。");
}
}
}
OrdinalIgnoreCase: 一致しています。
Ordinal: 一致していません。
基本的には「Ordinal」または「OrdinalIgnoreCase」を使用するのが最も安全で高速です。
言語固有の特殊な並べ替え(例えばドイツ語のウムラウトなど)が必要な場合にのみ、Culture系のオプションを検討しましょう。
Null値の取り扱いと安全性
文字列比較において注意が必要なのが、変数がnullである可能性です。
インスタンスメソッドであるstrA.Equals(strB)の場合、strAがnullだとNullReferenceExceptionが発生してしまいます。
しかし、String.Compareは静的メソッドであるため、引数にnullを渡しても例外が発生しません。

C#の仕様では、nullはどんな文字列よりも「前」にあると定義されています。
using System;
class Program
{
static void Main()
{
string str1 = null;
string str2 = "abc";
// nullとの比較でもエラーにならない
int result = String.Compare(str1, str2);
if (result < 0)
{
Console.WriteLine("nullは 'abc' より前に配置されます。");
}
// 両方がnullの場合は 0 (一致)
Console.WriteLine($"両方nullの比較: {String.Compare(null, null)}");
}
}
nullは 'abc' より前に配置されます。
両方nullの比較: 0
この性質により、String.Compareはヌルセーフな比較手段として非常に優秀です。
応用編:特定の範囲(部分文字列)を比較する
String.Compareには、文字列全体ではなく、指定したインデックスから特定の長さ分だけを比較する高度なオーバーロードも用意されています。
これは、大きなテキストデータの中から特定の部分を抽出せずに、そのまま比較したい場合にメモリ効率の面で有利です。
using System;
class Program
{
static void Main()
{
string text1 = "User: Tanaka";
string text2 = "Name: Tanaka";
// text1のインデックス6から6文字("Tanaka")と
// text2のインデックス6から6文字("Tanaka")を比較
int result = String.Compare(text1, 6, text2, 6, 6, StringComparison.Ordinal);
if (result == 0)
{
Console.WriteLine("部分文字列は一致しています。");
}
}
}
部分文字列は一致しています。
Substringメソッドで新しい文字列インスタンスを生成してから比較するよりも、メモリ消費(アロケーション)を抑えられるため、パフォーマンスが要求されるループ処理などで効果を発揮します。
比較演算子(==)やEqualsとの使い分け
C#には文字列を比べる方法が複数あるため、どれを使うべきか迷うことがあります。
以下の表を参考に、状況に応じて最適なものを選択してください。
| メソッド / 演算子 | 主な用途 | 特徴 |
|---|---|---|
== 演算子 | 単純な一致確認 | 直感的。内部でEqualsを呼ぶ。nullも扱える。 |
Equals | 一致確認(詳細設定あり) | StringComparisonを指定可能。インスタンスメソッド。 |
String.Compare | 大小比較・ソート | 前後関係がわかる。静的メソッドでnullに強い。 |
「ただ一致するか知りたいだけなら ==、並び替えたいなら String.Compare」という使い分けが最も一般的です。
ただし、大文字小文字を無視したい場合は、==では対応できないため、EqualsかString.Compareの出番となります。
まとめ
String.Compareは、C#における文字列操作の強力な武器です。
単なる一致確認に留まらず、辞書順での前後関係を数値で取得できる点が最大の実力です。
特にStringComparison.OrdinalIgnoreCaseを活用することで、実務で頻出する「大文字小文字を区別しない比較」を、安全かつ高速に実装できます。
また、静的メソッドであるため、null参照例外を気にせずに記述できるのも大きなメリットです。
今後、リストのソート処理やユーザー入力の柔軟な検証を行う際には、ぜひこの記事で紹介したString.Compareのテクニックを役立ててください。
適切な比較手法を選ぶことで、バグの少ない、洗練されたC#プログラムを構築できるようになります。
