280

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

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

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

(注: この例では等しいことを探しています。それ以下でも大きいものでもありませんが、それについても自由にコメントしてください)

4

11 に答える 11

238

これらの関数がどのように機能するかについての規則は次のとおりです。

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()と参照例外が発生しますが、onは発生しません。nullnull==

Object.ReferenceEquals(stringValue, otherStringValue)

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


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

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

于 2008-09-04T18:17:00.097 に答える
74

MSDN から:

「CompareTo メソッドは、主に並べ替えまたはアルファベット順の操作で使用するために設計されました。メソッド呼び出しの主な目的が 2 つの文字列が等しいかどうかを判断することである場合は、使用しないでください。2 つの文字列が等しいかどうかを判断するには、Equals メソッドを呼び出します。 "

彼らは、単に平等を求めるとき.Equalsの代わりに使用することを提案しています. クラスにとの.CompareTo間に違いがあるかどうかはわかりません。後で誰かがやって来て、そのクラスの演算子を再定義する場合に備えて、自分のクラスの代わりにorを使用することがあります。.Equals==string.EqualsObject.ReferenceEquals====

于 2008-09-04T17:49:27.743 に答える
50

BCL メソッドの違いに興味があるなら、Reflectorはあなたの友達です :-)

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

完全一致: 編集: 以前は常に Equals(string, string) 内でオブジェクト == 演算子を使用してオブジェクト参照を比較するという原則に基づいて == 演算子を使用していましたが、strA.Equals(strB) はまだ 1-11% のようですstring.Equals(strA, strB)、strA == strB、および string.CompareOrdinal(strA, strB) より全体的に高速です。同じ/異なる文字列長で、さまざまなサイズ (1B から 5MB) で、interned/non-interned 文字列値の両方で 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
于 2009-02-04T20:10:16.237 に答える
18

Edが言ったように、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;
于 2009-02-04T20:18:47.997 に答える
15

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


上記の各方法 (およびその他) には、特定の目的があります。それらの主な違いは、デフォルトで使用されているStringComparison Enumerationの種類です。いくつかのオプションがあります:

  • 現在の文化
  • CurrentCultureIgnoreCase
  • 不変文化
  • InvariantCultureIgnoreCase
  • 序数
  • 序数IgnoreCase

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

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

StringComparison Enumerationと文字列比較メソッドのオーバーロードは、.NET 2.0 以降に存在することに注意してください。


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

実際には、 IComparable.CompareTo Methodのタイプ セーフな実装です。デフォルトの解釈: CurrentCulture.

使用法:

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

したがって

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

String.Compare メソッド

多くのオーバーロードを持つString クラスの静的メンバー。デフォルトの解釈: CurrentCulture.

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

String.Equals メソッド

Object クラスからオーバーライドされ、タイプ セーフのためにオーバーロードされます。デフォルトの解釈: 序数。次の点に注意してください。

String クラスの等価メソッドには、静的 Equals静的演算子 ==、およびインスタンス メソッド Equalsが含まれます。


StringComparer クラス

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

StringComparer クラスを使用して、型固有の比較を作成し、ジェネリック コレクション内の要素を並べ替えることができます。Hashtable、Dictionary、SortedList、SortedList などのクラスは、ソートのために StringComparer クラスを使用します。

于 2013-03-07T12:31:21.327 に答える
7

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

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

于 2008-09-04T18:12:04.023 に答える
5

ここにリストしたフォームでは、2 つの間に大きな違いはありません。 現在のカルチャを使用して比較を行うメソッドをCompareTo呼び出すことになります。オペレーターによって呼び出されます。CompareInfoEquals==

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

その汎用性のために、私はString.Compare他のどの比較方法よりも多く使用していることに気づきました。必要なものを正確に指定できます。

于 2008-09-04T17:50:08.757 に答える
2

注意すべき大きな違いの 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");
于 2013-06-28T09:33:09.023 に答える
1
  • s1.CompareTo(s2): 主な目的が 2 つの文字列が等しいかどうかを判断することである場合は使用しないでください
  • s1 == s2: 大文字と小文字を区別できません
  • s1.Equals(s2, StringComparison): s1 が null の場合、NullReferenceExceptionをスローします
  • String.Equals(s2, StringComparison): 除去のプロセスにより、この静的メソッドは勝者です(2 つの文字列が等しいかどうかを判断する典型的な使用例を想定して)!
于 2017-12-14T18:32:16.513 に答える
-1

.Equalsを使用すると、読みやすくなります。

于 2008-09-04T18:03:34.013 に答える
-9

.Equalsを使用すると、StringComparisonオプションも取得できます。ケースなどを無視するのにとても便利です。

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

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

return a==b

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

bを次のように変更した場合:

b = "MYSTRING";

その場合、a.Equals(b)は偽ですが、

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

本当だろう

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

私は物事を省いていると確信していますが、詳細が必要な場合は、これで実験を開始するのに十分な情報になると思います。

于 2010-03-25T13:36:51.843 に答える