質問

C# での文字列の比較は非常に簡単です。実際、それを行うにはいくつかの方法があります。以下のブロックにいくつかリストしました。私が興味があるのは、それらの違いと、いつ一方を他方よりも使用すべきかということです。何が何でも避けるべきでしょうか?リストしていないものは他にもありますか?

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(注記:この例では、以下またはそれ以上ではなく平等を求めていますが、それについてもお気軽にコメントしてください)

役に立ちましたか?

解決

これらの関数がどのように機能するかのルールは次のとおりです。

stringValue.CompareTo(otherStringValue)

  1. null 文字列の前に来る
  2. それは使用しています CultureInfo.CurrentCulture.CompareInfo.Compare, これは、文化に依存した比較を使用することを意味します。これは次のことを意味するかもしれません ß と等しいと比較されます SS ドイツなどで

stringValue.Equals(otherStringValue)

  1. null 何にも等しいとはみなされません
  2. を指定しない限り、 StringComparison オプションを使用すると、直接の順序等価性チェックのように見えるものを使用します。 ß と同じではありません SS, あらゆる言語や文化において

stringValue == otherStringValue

  1. と同じではありません stringValue.Equals().
  2. == オペレータは静的メソッドを呼び出します Equals(string a, string b) メソッド (次に内部メソッドに送られます) EqualsHelper 比較をするために。
  3. 電話をかける .Equals()null 文字列が取得されます null 参照例外、オンの間 == ではない。

Object.ReferenceEquals(stringValue, otherStringValue)

参照が同じであることを確認するだけです。つまり、同じ内容を持つ 2 つの文字列だけではなく、文字列オブジェクトとそれ自体を比較しています。


メソッド呼び出しを使用する上記のオプションでは、比較方法を指定するためのより多くのオプションを備えたオーバーロードがあることに注意してください。

同等かどうかを確認したいだけの場合の私のアドバイスは、文化に依存した比較を使用するかどうかを決定してから、次を使用することです。 .CompareTo または .Equals, 、選択に応じて。

他のヒント

MSDN より:

「比較方法は、主にソートまたはアルファベット操作に使用するために設計されました。メソッドコールの主な目的が2つの文字列が同等かどうかを判断することである場合は、使用しないでください。2つの文字列が同等かどうかを判断するには、等しい方法を呼び出します。」

彼らは使用することを提案します .Equals の代わりに .CompareTo 平等だけを求めるとき。違いがあるかどうかはわかりませんが、 .Equals そして == のために string クラス。時々使います .Equals または Object.ReferenceEquals の代わりに == 後で誰かがやって来て、 == そのクラスの演算子。

BCL メソッドの違いについて知りたい場合は、 リフレクター あなたの友だちです :-)

私は次のガイドラインに従います。

完全に一致: 編集:以前は、Equals(string, string) 内でオブジェクト参照を比較するために object == 演算子が使用されるという原則に基づいて、常に == 演算子を使用していましたが、strA.Equals(strB) は依然として string より全体的に 1 ~ 11% 高速であるようです。 Equals(strA, strB)、strA == strB、および string.CompareOrdinal(strA, strB)。同じ/異なる文字列長、さまざまなサイズ (1B ~ 5MB) で、インターンされた文字列値とインターンされていない文字列値の両方について、StopWatch を使用してループ テストしました。

strA.Equals(strB)

人間が読める一致 (西洋文化、大文字と小文字を区別しない):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

人間が読める一致 (他のすべての文化、CultureInfo によって定義された大文字と小文字、アクセント、カナなどを区別しない):

string.Compare(strA, strB, myCultureInfo) == 0

人間が判読できるカスタム ルールとの一致 (他のすべてのカルチャ):

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

として エド 並べ替えには CompareTo が使用されます。

ただし、.Equals と == の間には違いがあります。

== に解決されます 本質的に 次のコード:

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

単純な理由は、次の場合は例外がスローされるためです。

string a = null;
string b = "foo";

bool equal = a.Equals(b);

また、次の場合は適用されません。

string a = null;
string b = "foo";

bool equal = a == b;

文字列比較の問題に関する適切な説明と実践方法は、この記事に記載されています。 Microsoft .NET 2.0での文字列の使用に関する新しい推奨事項 そしてまた .NET Framework で文字列を使用するためのベスト プラクティス.


前述のメソッド (およびその他) にはそれぞれ特定の目的があります。それらの主な違いは、どのような種類のものであるかです。 StringComparison 列挙体 彼らはデフォルトで使用しています。いくつかのオプションがあります。

  • 現在の文化
  • 現在の文化無視ケース
  • 不変文化
  • インバリアント文化無視ケース
  • 序数
  • OrdinalIgnoreCase

上記の各比較タイプは、異なるユースケースを対象としています。

  • 序数
    • 大文字と小文字を区別する内部識別子
    • XML や HTTP などの標準における大文字と小文字を区別する識別子
    • 大文字と小文字を区別するセキュリティ関連の設定
  • OrdinalIgnoreCase
    • 大文字と小文字を区別しない内部識別子
    • XML や HTTP などの標準における大文字と小文字を区別しない識別子
    • ファイル パス (Microsoft Windows の場合)
    • レジストリキー/値
    • 環境変数
    • リソース識別子 (ハンドル名など)
    • 大文字と小文字を区別しないセキュリティ関連の設定
  • InvariantCulture または InvariantCultureIgnoreCase
    • 一部の言語関連データが永続化されている
    • 固定のソート順を必要とする言語データの表示
  • CurrentCulture または CurrentCultureIgnoreCase
    • ユーザーに表示されるデータ
    • ほとんどのユーザー入力

ご了承ください StringComparison 列挙体 文字列比較メソッドのオーバーロードと同様に、.NET 2.0 以降に存在します。


String.CompareTo メソッド (文字列)

実際にはタイプセーフな実装です IComparable.CompareTo メソッド. 。デフォルトの解釈:現在の文化。

使用法:

CompareTo メソッドは、主に並べ替えまたはアルファベット順の操作で使用するために設計されました。

したがって

IComparable インターフェイスを実装すると、必ずこのメソッドが使用されます。

String.Compare メソッド

の静的メンバー 文字列クラス 多くの過負荷があります。デフォルトの解釈:現在の文化。

可能な限り、StringComparison パラメーターを含む Compare メソッドのオーバーロードを呼び出す必要があります。

String.Equals メソッド

オブジェクト クラスからオーバーライドされ、型安全性のためにオーバーロードされます。デフォルトの解釈:序数。次の点に注意してください。

String クラスの等価メソッドには、 静的等しい, 、 静的演算子 ==, 、 そしてその インスタンスメソッド Equals.


StringComparer クラス

特にソートを目的とした文字列比較を処理する別の方法もあります。

使用できます StringComparer クラス 型固有の比較を作成して、汎用コレクション内の要素を並べ替えます。Hashtable、Dictionary、SortedList、SortedList などのクラスは、並べ替えの目的で StringComparer クラスを使用します。

通常、これを実行する必要がある場合、パフォーマンスは 99% 重要ではありませんが、これをループで数百万回実行する必要がある場合は、文字が見つかるとすぐに .Equals または == を使用することを強くお勧めします。一致しない場合は全体が false としてスローされますが、CompareTo を使用する場合は、どの文字が他の文字よりも小さいかを判断する必要があり、パフォーマンス時間がわずかに低下します。

アプリをさまざまな国で実行する場合は、CultureInfo の影響を検討し、場合によっては .Equals を使用することをお勧めします。私は実際に米国向けのアプリのみを作成しているため (誰かが適切に動作しなかったとしても気にしません)、常に == を使用します。

ここに挙げた形式では、両者に大きな違いはありません。 CompareTo 結局電話することになる CompareInfo 現在のカルチャを使用して比較を行うメソッド。 Equals によって呼ばれます == オペレーター。

過負荷を考慮すると、状況は異なります。 Compare そして == 現在のカルチャは文字列の比較にのみ使用できます。 Equals そして String.Compare 取ることができます StringComparison カルチャを区別しない、または大文字と小文字を区別しない比較を指定できる列挙型引数。のみ String.Compare を指定できます CultureInfo デフォルトのカルチャ以外のカルチャを使用して比較を実行します。

その汎用性の高さから、私は次のように使っています。 String.Compare 他のどの比較方法よりも優れています。欲しいものを正確に指定できます。

注意すべき大きな違いの 1 つは、最初の文字列が null の場合、 .Equals() は例外をスローしますが、 == は例外をスローしないことです。

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");
  • s1.比較対象(s2): 2 つの文字列が同等かどうかを判断することが主な目的の場合は使用しないでください
  • s1 == s2: 大文字と小文字を無視できません
  • s1.Equals(s2, StringComparison): s1 が null の場合は NullReferenceException をスローします
  • String.Equals(s2, StringComparison): 消去法により、これは、 静的 方法は 勝者 (2 つの文字列が同等かどうかを判断する典型的な使用例を想定しています)!

.Equals を使用すると、非常に簡単になります。 読む.

.Equals を使用すると、StringComparison オプションも利用できます。大文字と小文字やその他のものを無視するのに非常に便利です。

ところで、これは false と評価されます

string a = "myString";
string b = "myString";

return a==b

== は a と b (ポインター) の値を比較するため、ポインターがメモリ内の同じオブジェクトを指している場合にのみ true と評価されます。.Equals はポインターを逆参照し、ポインターに格納されている値を比較します。ここでは a.Equals(b) が true になります。

b を次のように変更すると、

b = "MYSTRING";

その場合、a.Equals(b) は false になりますが、

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

本当だろう

a.CompareTo(b) は、ポインターの値を比較する文字列の CompareTo 関数を呼び出し、a に格納されている値が b に格納されている値より小さい場合は <0 を返し、a.Equals(b) が true の場合は 0 を返します。それ以外の場合は >0。ただし、これは大文字と小文字が区別されます。CompareTo が大文字と小文字を区別しないようにするオプションがあると思いますが、今は調べる時間がありません。他の人がすでに述べたように、これは並べ替えのために行われます。この方法で等しいかどうかを比較すると、不必要なオーバーヘッドが発生します。

省略している部分はあると思いますが、さらに詳細が必要な場合は、これで実験を始めるのに十分な情報になると思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top