C# で文字列を比較する方法How to compare strings in C#

文字列を比較して、次の 2 つの質問のいずれかに回答します。"これら 2 つの文字列は等しいですか"You compare strings to answer one of two questions: "Are these two strings equal?" または "これらを並べ替えるときにどのような順序でこれらの文字列を配置しますか"or "In what order should these strings be placed when sorting them?"

これら 2 つの質問は、文字列比較に影響する要因によって複雑になります。Those two questions are complicated by factors that affect string comparisons:

  • 序数に基づく比較または言語的な比較を選択することができます。You can choose an ordinal or linguistic comparison.
  • 大文字小文字が重要かどうかを選択できます。You can choose if case matters.
  • カルチャに固有の比較を選択できます。You can choose culture-specific comparisons.
  • 言語的な比較は、カルチャおよびプラットフォームに依存します。Linguistic comparisons are culture and platform-dependent.

注意

この記事の C# 例は、Try.NET インライン コード ランナーとプレイグラウンドで実行されます。The C# examples in this article run in the Try.NET inline code runner and playground. [実行] ボタンを選択すると、対話型ウィンドウで例が実行されます。Select the Run button to run an example in an interactive window. コードを実行したら、コードを変更し、 [実行] をもう一度選択して変更後のコードを実行できます。Once you execute the code, you can modify it and run the modified code by selecting Run again. 変更後のコードが対話型ウィンドウで実行されるか、コンパイルできなかった場合、対話型ウィンドウにすべての C# コンパイラ エラー メッセージが表示されます。The modified code either runs in the interactive window or, if compilation fails, the interactive window displays all C# compiler error messages.

文字列を比較するときに、それらの間で順序を定義します。When you compare strings, you define an order among them. 比較は、文字列のシーケンスの並べ替えに使用されます。Comparisons are used to sort a sequence of strings. シーケンスが既知の順序の場合、ソフトウェアと人間の両方が簡単に検索できます。Once the sequence is in a known order, it is easier to search, both for software and for humans. その他の比較では、文字列が等しいかどうかを確認する場合があります。Other comparisons may check if strings are the same. これらの類似性チェックは等値に似ていますが、大文字小文字の違いなど、いくつかの違いは無視される場合があります。These sameness checks are similar to equality, but some differences, such as case differences, may be ignored.

既定の序数の比較Default ordinal comparisons

最も一般的な演算であるThe most common operations:

では、序数の比較、大文字小文字の比較、現在のカルチャが使用されます。use an ordinal comparison, a case-sensitive comparison, and use the current culture. これらの結果を次の例に示します。The results are shown in the following example:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

result = root.Equals(root2, StringComparison.Ordinal);
Console.WriteLine($"Ordinal comparison: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");

Console.WriteLine($"Using == says that <{root}> and <{root2}> are {(root == root2 ? "equal" : "not equal")}");               

既定の序数の比較では、文字列を比較するときに言語の規則を考慮しません。The default ordinal comparison does not take linguistic rules into account when comparing strings. 2 つの文字列のそれぞれの Char オブジェクトのバイナリ値を比較します。It compares the binary value of each Char object in two strings. その結果、既定の序数の比較でも大文字と小文字が区別されます。As a result, the default ordinal comparison is also case-sensitive.

String.EqualsString.Equality を使用した等価性のテストは、String.CompareToCompare(String, String) のメソッドを使用した文字列の比較とは異なります。Note that the test for equality with String.Equals and String.Equality differs from string comparison using the String.CompareTo and Compare(String, String) methods. 等価性のテストでは大文字と小文字を区別する序数の比較が行われますが、比較メソッドでは大文字と小文字だけでなく、現在のカルチャを使用してカルチャを区別する比較が行われます。While the tests for equality perform a case-sensitive ordinal comparison, the comparison method perform a case-sensitive, culture-sensitive comparison using the current culture. 既定の比較メソッドでは多くの場合、さまざまな種類の比較が実行されるため、実行する比較の種類を明示的に指定するオーバーロードを呼び出して、コードの意図を常に明確にすることをお勧めします。Because the default comparison methods often perform different types of comparisons, we recommend that you always make the intent of your code clear by calling an overload that explicitly specifies the type of comparison to perform.

大文字と小文字を区別しない、序数に基づく比較Case-insensitive ordinal comparisons

String.Equals(String, StringComparison) メソッドでは、StringComparison.OrdinalIgnoreCaseStringComparison 値を指定して、The String.Equals(String, StringComparison) method enables you to specify a StringComparison value of StringComparison.OrdinalIgnoreCase 大文字と小文字を区別しない、序数に基づく比較ができるようにします。for a case-insensitive ordinal comparison. StringComparison 引数に StringComparison.OrdinalIgnoreCase の値を指定すると、大文字と小文字を区別しない序数に基づく比較が実行される、静的な String.Compare(String, String, StringComparison) メソッドもあります。There is also a static String.Compare(String, String, StringComparison) method that performs a case-insensitive ordinal comparison if you specify a value of StringComparison.OrdinalIgnoreCase for the StringComparison argument. これを次のコードに示します。These are shown in the following code:

string root = @"C:\users";
string root2 = @"C:\Users";

bool result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
bool areEqual = String.Equals(root, root2, StringComparison.OrdinalIgnoreCase);
int comparison = String.Compare(root, root2, comparisonType: StringComparison.OrdinalIgnoreCase);

Console.WriteLine($"Ordinal ignore case: <{root}> and <{root2}> are {(result ? "equal." : "not equal.")}");
Console.WriteLine($"Ordinal static ignore case: <{root}> and <{root2}> are {(areEqual ? "equal." : "not equal.")}");
if (comparison < 0)
    Console.WriteLine($"<{root}> is less than <{root2}>");
else if (comparison > 0)
    Console.WriteLine($"<{root}> is greater than <{root2}>");
else
    Console.WriteLine($"<{root}> and <{root2}> are equivalent in order");

大文字と小文字を区別しない、序数に基づく比較を実行すると、これらのメソッドではインバリアント カルチャの大文字と小文字の区別が使用されます。When performing a case-insensitive ordinal comparison, these methods use the casing conventions of the invariant culture.

言語的な比較Linguistic comparisons

現在のカルチャの言語の規則を使用して文字列の順序を指定することもできます。Strings can also be ordered using linguistic rules for the current culture. これは、"単語の並べ替え順序" と呼ばれることもあります。This is sometimes referred to as "word sort order." 言語的な比較を実行するときには、一部の英数字以外の Unicode 文字に、特別な重みが割り当てられる場合があります。When you perform a linguistic comparison, some nonalphanumeric Unicode characters might have special weights assigned. たとえば、ハイフン ("-") に割り当てられる重みは非常に小さいため、並べ替え順序で "coop" と "co-op" の出現位置が隣接します。For example, the hyphen "-" may have a very small weight assigned to it so that "co-op" and "coop" appear next to each other in sort order. さらに、いくつかの Unicode 文字が Char インスタンスのシーケンスと等しくなる可能性があります。In addition, some Unicode characters may be equivalent to a sequence of Char instances. 次の例では、ドイツ語で "They dance in the street" という語句をThe following example uses the phrase "They dance in the street." 一方の文字列では "ss" (U+0073 U+0073)、もう一方の文字列では 'ß' (U+00DF) を使って表しています。in German with the "ss" (U+0073 U+0073) in one string and 'ß' (U+00DF) in another. 言語的に (Windows では)、"en-US" と "de-DE" の両方のカルチャで、"ss" はドイツ語の Essetz: 'ß' 文字と同じです。Linguistically (in Windows), "ss" is equal to the German Esszet: 'ß' character in both the "en-US" and "de-DE" cultures.

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

bool equal = String.Equals(first, second, StringComparison.InvariantCulture);
Console.WriteLine($"The two strings {(equal == true ? "are" : "are not")} equal.");
showComparison(first, second);

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words);
showComparison(word, other);
showComparison(words, other);
void showComparison(string one, string two)
{
    int compareLinguistic = String.Compare(one, two, StringComparison.InvariantCulture);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using invariant culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using invariant culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using invariant culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

このサンプルでは、言語的な比較に依存するオペレーティング システムの性質を示します。This sample demonstrates the operating system-dependent nature of linguistic comparisons. 対話型ウィンドウのホストは、Linux ホストです。The host for the interactive window is a Linux host. 言語比較および序数比較は、同じ結果を生成します。The linguistic and ordinal comparisons produce the same results. Windows ホストで同じこのサンプルを実行する場合、次の出力が表示されます。If you ran this same sample on a Windows host, you would see the following output:

<coop> is less than <co-op> using invariant culture
<coop> is greater than <co-op> using ordinal comparison
<coop> is less than <cop> using invariant culture
<coop> is less than <cop> using ordinal comparison
<co-op> is less than <cop> using invariant culture
<co-op> is less than <cop> using ordinal comparison

Windows では、言語的な比較から序数に基づく比較に変更した場合に、"cop"、"coop"、および "co-op" の並べ替え順序は変更されます。On Windows, the sort order of "cop", "coop", and "co-op" change when you change from a linguistic comparison to an ordinal comparison. ドイツ語の 2 つの文も、異なる比較の種類を使用して異なる方法で比較されます。The two German sentences also compare differently using the different comparison types.

特定のカルチャを使用した比較Comparisons using specific cultures

このサンプルでは en-US と de-DE のカルチャの CultureInfo オブジェクトを格納しています。This sample stores CultureInfo objects for the en-US and de-DE cultures. 比較は、カルチャ固有の比較を確保するために CultureInfo オブジェクトを使用して実行されます。The comparisons are performed using a CultureInfo object to ensure a culture-specific comparison.

使用されるカルチャは言語的な比較に影響します。The culture used affects linguistic comparisons. 次の例は、"en-US" カルチャと "de-DE" カルチャを使用する 2 つのドイツ語の文の比較の結果を示しています。The following example shows the results of comparing the two German sentences using the "en-US" culture and the "de-DE" culture:

string first = "Sie tanzen auf der Straße.";
string second = "Sie tanzen auf der Strasse.";

Console.WriteLine($"First sentence is <{first}>");
Console.WriteLine($"Second sentence is <{second}>");

var en = new System.Globalization.CultureInfo("en-US");

// For culture-sensitive comparisons, use the String.Compare 
// overload that takes a StringComparison value.
int i = String.Compare(first, second, en, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {en.Name} returns {i}.");

var de = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, de, System.Globalization.CompareOptions.None);
Console.WriteLine($"Comparing in {de.Name} returns {i}.");

bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine($"The two strings {(b ? "are" : "are not")} equal.");

string word = "coop";
string words = "co-op";
string other = "cop";

showComparison(word, words, en);
showComparison(word, other, en);
showComparison(words, other, en);
void showComparison(string one, string two, System.Globalization.CultureInfo culture)
{
    int compareLinguistic = String.Compare(one, two, en, System.Globalization.CompareOptions.None);
    int compareOrdinal = String.Compare(one, two, StringComparison.Ordinal);
    if (compareLinguistic < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using en-US culture");
    else if (compareLinguistic > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using en-US culture");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using en-US culture");
    if (compareOrdinal < 0)
        Console.WriteLine($"<{one}> is less than <{two}> using ordinal comparison");
    else if (compareOrdinal > 0)
        Console.WriteLine($"<{one}> is greater than <{two}> using ordinal comparison");
    else
        Console.WriteLine($"<{one}> and <{two}> are equivalent in order using ordinal comparison");
}

カルチャに依存した比較は、一般的にユーザーによる文字列入力とユーザーによる他の文字列入力の比較および並べ替えに使用されます。Culture-sensitive comparisons are typically used to compare and sort strings input by users with other strings input by users. これらの文字列の文字および並べ替え規則は、ユーザーのコンピューターのロケールによって異なる場合があります。The characters and sorting conventions of these strings might vary depending on the locale of the user's computer. 同一の文字を含む文字列でも、現在のスレッドのカルチャに応じて、異なる方法で並べ替えられます。Even strings that contain identical characters might sort differently depending on the culture of the current thread. さらに、Windows コンピューターでローカルでこのサンプル コードを試すと、次の結果が表示されます。In addition, try this sample code locally on a Windows machine, and you will the following results:

<coop> is less than <co-op> using en-US culture
<coop> is greater than <co-op> using ordinal comparison
<coop> is less than <cop> using en-US culture
<coop> is less than <cop> using ordinal comparison
<co-op> is less than <cop> using en-US culture
<co-op> is less than <cop> using ordinal comparison

言語的な比較は、現在のカルチャに依存し、OS に依存します。Linguistic comparisons are dependent on the current culture, and are OS dependent. 文字列の比較を使用する場合は、これを考慮する必要があります。You must take that into account when you work with string comparisons.

配列の言語的な並べ替えと文字列の検索Linguistic sorting and searching strings in arrays

次の例は、現在のカルチャに依存する言語的な比較を使用して、配列内の文字列を並べ替えおよび検索する方法を示しています。The following examples show how to sort and search for strings in an array using a linguistic comparison dependent on the current culture. System.StringComparer パラメーターを取得する静的な Array メソッドを使用します。You use the static Array methods that take a System.StringComparer parameter.

この例では、現在のカルチャを使用して文字列の配列を並べ替える方法を示します。This example shows how to sort an array of strings using the current culture:

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

// Specify Ordinal to demonstrate the different behavior.
Array.Sort(lines, StringComparer.CurrentCulture);

foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

配列が並べ替えられた後は、バイナリ検索を使用してエントリを検索できます。Once the array is sorted, you can search for entries using a binary search. バイナリ検索は、コレクションの中央で開始され、要求された文字列がコレクションのどちらの半分に含まれているかを判断します。A binary search starts in the middle of the collection to determine which half of the collection would contain the sought string. 各後続の比較は、半分にコレクションの残りの部分を半分に細分化します。Each subsequent comparison subdivides the remaining part of the collection in half. 配列は StringComparer.CurrentCulture を使用して並べ替えられます。The array is sorted using the StringComparer.CurrentCulture. ローカル関数 ShowWhere は、文字列が見つかった場所に関する情報を表示します。The local function ShowWhere displays information about where the string was found. 文字列が見つからなかった場合、返された値は、見つからなかった場合にどこにあるべきかを示します。If the string was not found, the returned value indicates where it would be if it were found.

string[] lines = new string[]
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
Array.Sort(lines, StringComparer.CurrentCulture);

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = Array.BinarySearch(lines, searchString, StringComparer.CurrentCulture);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(T[] array, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{array[index - 1]} and ");

        if (index == array.Length)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{array[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

コレクションの序数に基づく並べ替えと検索Ordinal sorting and searching in collections

次のコードでは、System.Collections.Generic.List<T> コレクション クラスを使用して文字列を格納します。The following code uses the System.Collections.Generic.List<T> collection class to store strings. 文字列は、List<T>.Sort メソッドを使用して並べ替えられます。The strings are sorted using the List<T>.Sort method. このメソッドでは、2 つの文字列の順序を比較するデリゲートが必要です。This method needs a delegate that compares and orders two strings. String.CompareTo メソッドは、その比較関数を提供します。The String.CompareTo method provides that comparison function. このサンプルを実行し、順序を確認します。Run the sample and observe the order. この並べ替え操作では、大文字小文字を区別する序数の並べ替えを使用します。This sort operation uses an ordinal case sensitive sort. 静的な String.Compare メソッドを使用し、別の比較規則を指定します。You would use the static String.Compare methods to specify different comparison rules.

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};

Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

Console.WriteLine("\n\rSorted order:");

lines.Sort((left, right) => left.CompareTo(right)); 
foreach (string s in lines)
{
    Console.WriteLine($"   {s}");
}

並べ替えられたら、バイナリ検索を使用して文字列の一覧を検索できます。Once sorted, the list of strings can be searched using a binary search. 次の例では、同じ比較関数を使用して、並べ替えられた一覧を検索する方法を示します。The following sample shows how to search the sorted listed using the same comparison function. ローカル関数 ShowWhere は、要求されたテキストの場所、またはあるべき場所を示します。The local function ShowWhere shows where the sought text is or would be:

List<string> lines = new List<string>
{
    @"c:\public\textfile.txt",
    @"c:\public\textFile.TXT",
    @"c:\public\Text.txt",
    @"c:\public\testfile2.txt"
};
lines.Sort((left, right) => left.CompareTo(right));

string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine($"Binary search for <{searchString}>");
int result = lines.BinarySearch(searchString);
ShowWhere<string>(lines, result);

Console.WriteLine($"{(result > 0 ? "Found" : "Did not find")} {searchString}");

void ShowWhere<T>(IList<T> collection, int index)
{
    if (index < 0)
    {
        index = ~index;

        Console.Write("Not found. Sorts between: ");

        if (index == 0)
            Console.Write("beginning of sequence and ");
        else
            Console.Write($"{collection[index - 1]} and ");

        if (index == collection.Count)
            Console.WriteLine("end of sequence.");
        else
            Console.WriteLine($"{collection[index]}.");
    }
    else
    {
        Console.WriteLine($"Found at index {index}.");
    }
}

並べ替えと検索に常に同じ種類の比較を使用してください。Always make sure to use the same type of comparison for sorting and searching. 並べ替えと検索に異なる種類の比較を使用すると、予期しない結果になります。Using different comparison types for sorting and searching produces unexpected results.

System.Collections.HashtableSystem.Collections.Generic.Dictionary<TKey,TValue>、および System.Collections.Generic.List<T> などのコレクション クラスには、要素またはキーの種類が string の場合、System.StringComparer パラメーターを取るコンストラクターが用意されています。Collection classes such as System.Collections.Hashtable, System.Collections.Generic.Dictionary<TKey,TValue>, and System.Collections.Generic.List<T> have constructors that take a System.StringComparer parameter when the type of the elements or keys is string. 通常は、これらのコンストラクターをできるだけ使用し、StringComparer.Ordinal または StringComparer.OrdinalIgnoreCase を指定する必要があります。In general, you should use these constructors whenever possible, and specify either StringComparer.Ordinal or StringComparer.OrdinalIgnoreCase.

参照の等価性と文字列インターンReference equality and string interning

どの例でも ReferenceEquals を使用していません。None of the samples have used ReferenceEquals. このメソッドは、2 つの文字列が同じオブジェクトかどうかを判断します。This method determines if two strings are the same object. これは、文字列比較で一貫性のない結果につながる可能性があります。This can lead to inconsistent results in string comparisons. 次の例は、C# の文字列のインターン機能を示しています。The following example demonstrates the string interning feature of C#. プログラムで 2 つ以上の同じ文字列変数を宣言すると、コンパイラはそれらをすべて同じ場所に保管します。When a program declares two or more identical string variables, the compiler stores them all in the same location. ReferenceEquals メソッドを呼び出すと、2 つの文字列がメモリ内の同じオブジェクトを実際に参照していることを確認できます。By calling the ReferenceEquals method, you can see that the two strings actually refer to the same object in memory. インターン処理を回避するには、String.Copy メソッドを使用します。Use the String.Copy method to avoid interning. コピーが行われた後、同じ値が含まれていても、2 つの文字列は別の記憶場所を使用します。After the copy has been made, the two strings have different storage locations, even though they have the same value. 次の例を実行し、文字列 abインターン処理されることを示します。これは、同じ記憶域を共有することを意味します。Run the following sample to show that strings a and b are interned meaning they share the same storage. 文字列 ac は異なります。The strings a and c are not.

string a = "The computer ate my source code.";
string b = "The computer ate my source code.";

if (String.ReferenceEquals(a, b))
    Console.WriteLine("a and b are interned.");
else
    Console.WriteLine("a and b are not interned.");

string c = String.Copy(a);

if (String.ReferenceEquals(a, c))
    Console.WriteLine("a and c are interned.");
else
    Console.WriteLine("a and c are not interned.");

注意

文字列の等価をテストする場合、実行する比較の種類を明示的に指定するメソッドを使用する必要があります。When you test for equality of strings, you should use the methods that explicitly specify what kind of comparison you intend to perform. コードを保守しやすく、読みやすくすることができます。Your code is much more maintainable and readable. StringComparison 列挙パラメーターを取る System.String および System.Array クラスのメソッドのオーバーロードを使用します。Use the overloads of the methods of the System.String and System.Array classes that take a StringComparison enumeration parameter. 実行する比較の種類を指定します。You specify which type of comparison to perform. 等価をテストするときには、== および != 演算子を使用しないでください。Avoid using the == and != operators when you test for equality. String.CompareTo インスタンス メソッドは常に、序数に基づいた大文字小文字を区別する比較を実行します。The String.CompareTo instance methods always perform an ordinal case-sensitive comparison. これらは、文字列をアルファベット順に並べ替える場合に適しています。They are primarily suited for ordering strings alphabetically.

String.Intern メソッドを呼び出すことで、文字列をインターンしたり、既存のインターンされた文字列への参照を取得したりできます。You can intern a string or retrieve a reference to an existing interned string by calling the String.Intern method. 文字列がインターンされているかどうかを確認するには、String.IsInterned メソッドを呼び出します。To determine whether a string is interned, call the String.IsInterned method.

関連項目See also