c# - C#の文字列比較メソッドの違い


C#の文字列を比較するのは簡単です。 実際には、いくつかの方法があります。 私は下のブロックにいくつか挙げました。 私が興味を持っているのは、それらの違いと、他のものよりも使い分けるべきときです。 1つのコストで回避する必要がありますか? 私はまだリストに載っていないのですか?

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

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

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




Answers


これらの関数の動作の規則は次のとおりです。

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(文字列a、文字列b)メソッドを呼び出します(これは、比較を行うために内部のEqualsHelperに送られます)。
  3. nullの文字列で.Equals()を呼び出すと、null参照例外が返されますが、==ではnullが返されます。

Object.ReferenceEquals(stringValue、otherStringValue):

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

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

あなたが単に平等をチェックしたいのであれば私のアドバイスは、文化依存の比較を使うかしないかを選択し、選択に応じて.CompareToまたは.Equalsを使用することです。




MSDNから:

2つの文字列が等しいかどうかを判断するには、Equalsメソッドを呼び出します。このメソッドは、2つの文字列が等しいかどうかを判断するために使用します。 "

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




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

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

厳密な一致: 編集:私はこれまでequals(string、string)の中のオブジェクト==演算子を使ってオブジェクト参照を比較していましたが、strA.Equals(strB)はまだ1〜11% string.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



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;



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

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

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

上記の比較型のそれぞれは、さまざまなユースケースをターゲットにしています。

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

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

String.CompareToメソッド(String)

実際にIComparable.CompareToメソッドの型の安全な実装です。 デフォルトの解釈:CurrentCulture。

使用法:

CompareToメソッドは、ソートまたはアルファベット順の操作で主に使用するために設計されています

従って

IComparableインターフェイスを実装するには、必ずこのメソッドを使用します

String.Compareメソッド

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

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

String.Equalsメソッド

Objectクラスからオーバーライドされ、型の安全のためにオーバーロードされます。 デフォルトの解釈:順序。 注意:

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

StringComparerクラス

文字列の比較に対処する別の方法もあります。特にソートを目指しています。

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




あなたがこれを行う必要がある時代の99%でその性能が重要ではないのですが、これを数百万回繰り返す必要があるなら、私はあなたが文字を見つけたら直ちに.Equalsや==を使うことを強く勧めます一致しない場合はfalseを返しますが、CompareToを使用すると、どちらの文字が他の文字よりも小さいかを把握して、パフォーマンスの時間が少し悪化します。

あなたのアプリケーションが異なる国で動いているなら、CultureInfoの意味を見て、おそらく.Equalsを使うことをお勧めします。 私は実際に米国向けのアプリしか書いていないので(それが誰かによって正しく動作しないかどうかは気にしないでください)、私は常に==を使用します。




あなたがここに挙げた形では、2つの違いはあまりありません。 CompareToは、現在のカルチャを使用して比較を行うCompareInfoメソッドを呼び出して終了します。 Equals==演算子によって呼び出されます。

過負荷を考慮すると、物事が異なることになります。 Compare==は現在のカルチャのみを使用して文字列を比較することができます。 EqualsおよびString.Compareは、 StringComparison -SensitiveまたはStringComparison -insensitiveの比較を指定できるStringComparison列挙型引数を取ります。 String.CompareのみがCultureInfoを指定し、デフォルトのカルチャ以外のカルチャを使用して比較を実行できます。

その汎用性のため、私はString.Compare他の比較メソッドよりも多く使用しています。 それは私が欲しいものを正確に指定することができます。




注意すべき大きな違いは、最初の文字列がnullの場合、Escape()は例外をスローします。ただし、==は例外ではありません。

       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");



.Equalsを使うことは読みやすくなります




CompareToは、文字列と文字列オブジェクトを比較し、int値を返します。 値が0の場合は、文字列が等しいことを意味します。

string country = "southindia";
object ob1 = country.Clone();
Console.WriteLine( country.CompareTo(ob1));

string country = "southindia";
string cou = "insia";
int n = country.CompareTo(cou);
Console.WriteLine( n );



.Equalsを使うと、StringComparisonオプションも得られます。 大文字と小文字を無視するのに非常に便利です。

btw、これはfalseと評価されます

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

return a==b

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

bをbに変更した場合:

b = "MYSTRING";

a.Equals(b)はfalseですが、

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

本当だろう

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

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