633

等しいかどうかC#の2つの文字列を比較する場合、InvariantCultureとOrdinalの比較の違いは何ですか?

4

9 に答える 9

338

不変文化

「標準」の文字順序セット (a、b、c、... など) を使用します。これは、文字を異なる順序でソートする特定のロケールとは対照的です (ロケールによっては、'a-with-acute' が 'a' の前または後にある場合があります)。

序数

一方、文字を表す生のバイトの値だけを調べます。


さまざまな StringComparison 値の結果を示す素晴らしいサンプルがhttp://msdn.microsoft.com/en-us/library/e6883c06.aspxにあります。最後までずっと、それは示しています(抜粋):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

InvariantCulture では (U+0069、U+0049、U+00131)、Ordinal では (U+0049、U+0069、U+00131) が生成されることがわかります。

于 2009-01-29T18:44:33.433 に答える
137

.NET Framework で文字列を使用するためのベスト プラクティスを示す:

  • カルチャに依存しない文字列マッチングの安全なデフォルトとして、比較にStringComparison.Ordinalorを使用します。StringComparison.OrdinalIgnoreCase
  • StringComparison.Ordinalまたはとの比較を使用して、StringComparison.OrdinalIgnoreCaseパフォーマンスを向上させます。
  • 比較が言語的に無関係である場合 (たとえば、シンボリック) に基づいて、文字列操作の代わりに非言語的なStringComparison.Ordinalor値を使用します。StringComparison.OrdinalIgnoreCaseCultureInfo.InvariantCulture

そして最後に:

  • StringComparison.InvariantCultureほとんどの場合、 に基づく文字列演算は使用しないでください。数少ない例外の 1 つは、言語的に意味があるが文化的に不可知なデータを永続化する場合です。
于 2014-02-25T10:48:40.357 に答える
60

もう 1 つの便利な違い (アクセントが一般的でない英語) は、InvariantCulture の比較では、最初に大文字と小文字を区別せずに文字列全体を比較し、必要に応じて (および要求された場合)、最初に個別の文字のみを比較した後、大文字と小文字を区別します。(もちろん、大文字と小文字を区別しない比較を行うこともできます。) 修正:アクセント付きの文字は、同じ文字の別のフレーバーと見なされ、文字列は最初にアクセントを無視して比較され、次に一般的な文字がすべて一致する場合に考慮されます (大文字と小文字を区別しない比較で最終的に無視されないことを除いて、大文字と小文字が異なる場合と同様)。これにより、最初のアクセントの違いで完全に分離されるのではなく、他の点では同じ単語のアクセント付きバージョンが互いに近くにグループ化されます。これは、辞書で一般的に見られる並べ替え順序です。大文字の単語は対応する小文字のすぐ隣に表示され、アクセント付きの文字は対応するアクセントのない文字の近くに表示されます。

序数比較では、最初の相違点で停止して、数値の文字値を厳密に比較します。これにより、大文字が小文字から完全に分離されてソートされます (そして、アクセント付きの文字はおそらく小文字から分離されます)。

また、InvariantCulture は大文字が小文字よりも大きいと見なしますが、Ordinal は大文字が小文字よりも小さいと見なします (コンピューターが小文字を使用する前の昔からの ASCII の引き継ぎで、大文字が最初に割り当てられたため、小文字よりも値が小さくなりました)。後で追加)。

たとえば、序数では次のようになります。"0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

そしてInvariantCultureによる:"0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"

于 2009-02-09T19:06:20.740 に答える
35

質問はequalityに関するものですが、視覚的に簡単に参照できるように、いくつかの文化を使用して並べ替えられたいくつかの文字列の順序が、そこにあるいくつかの特異性を示しています。

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb ぁ あ ァ ア 亜 A
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß ぁ あ ァ ア 亜 A
--------------------------------------------------------------------
InvariantCulture 0 9 a A A ä Ä aa ab aB Ab äb Äb ss ß ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ß ss ァ ぁ ア あ 亜
--------------------------------------------------------------------
da-DK            0 9 a A A ab aB Ab ss ß ä Ä äb Äb aa ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ab aB ab ß ss Ä ä Äb äb aa ァ ぁ ア あ 亜
--------------------------------------------------------------------
de-DE            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
en-US            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
ja-JP            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜

所見:

  • de-DEja-JP、およびen-US同じ方法で並べ替えます
  • Invariant上記の 3 つの文化ssßは異なります。
  • da-DK並べ方がかなり違う
  • フラグは、IgnoreCaseサンプリングされたすべての文化にとって重要です

上記の表を生成するために使用されるコード:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "亜" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}
于 2014-06-10T23:39:49.960 に答える
28

インバリアントは、言語的に適切なタイプの比較です。
Ordinal はバイナリ タイプの比較です。(高速) http://www.siao2.com/2004/12/29/344136.aspx
を参照

于 2010-06-02T20:56:59.143 に答える
7

InvariantCultureIgnoreCase と OrdinalIgnoreCase を使用した文字列等価比較で同じ結果が得られない例を次に示します。

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);

これを実行すると、equals1 が false、equals2 が true になります。

于 2015-07-11T21:22:57.947 に答える
-8

InvariantCulture をオーバーロードとして受け入れる文字列メソッドでは、常に InvariantCulture を使用するようにしてください。InvariantCulture を使用することで、安全な側にいます。多くの .NET プログラマーはこの機能を使用しないかもしれませんが、ソフトウェアが異なるカルチャで使用される場合、InvariantCulture は非常に便利な機能です。

于 2009-02-18T14:52:55.837 に答える