掲題の通りですが、コードの書き方はあれど結果をまとめてあるものが見当たらず毎回コードを動かして確認しているので、備忘録としてまとめます。直感と異なる挙動もあり覚えるのも容易ではありません。
環境:.NET ver 6.0.300
3行で
- 大文字小文字を区別する/しないなら
StringComparison
を受け取るオーバーロードに明示的に指定
- 全角半角の区別する/しないは癖が強く挙動に一貫性がないので注意が必要
- .NETのバージョンによって挙動が異なりそうなので要実運用環境テスト
参考
string.Equals
等しければTrue
、異なればFalse
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
True |
False |
False |
False |
"TEST" |
False |
True |
False |
False |
"test" |
False |
False |
True |
False |
"TEST" |
False |
False |
False |
True |
StringComparison.OrdinalIgnoreCase
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
True |
True |
False |
False |
"TEST" |
True |
True |
False |
False |
"test" |
False |
False |
True |
True |
"TEST" |
False |
False |
True |
True |
-
StringComparison.CurrentCulture
(ja-JP)
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
True |
False |
True |
False |
"TEST" |
False |
True |
False |
True |
"test" |
True |
False |
True |
False |
"TEST" |
False |
True |
False |
True |
-
StringComparison.CurrentCultureIgnoreCase
(ja-JP)
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
True |
True |
False |
False |
"TEST" |
True |
True |
False |
False |
"test" |
False |
False |
True |
True |
"TEST" |
False |
False |
True |
True |
StringComparer.Equals
string.Equals
と同様
new CultureInfo("ja-JP").CompareInfo.Compare
等しければ0
、異なれば並べ替え順序によって負か正の値
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
<0 |
0 |
<0 |
"TEST" |
>0 |
0 |
>0 |
0 |
"test" |
0 |
<0 |
0 |
<0 |
"TEST" |
>0 |
0 |
>0 |
0 |
CompareOptions.IgnoreCase
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
0 |
<0 |
<0 |
"TEST" |
0 |
0 |
<0 |
<0 |
"test" |
>0 |
>0 |
0 |
0 |
"TEST" |
>0 |
>0 |
0 |
0 |
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
>0 |
<0 |
<0 |
"TEST" |
<0 |
0 |
<0 |
<0 |
"test" |
>0 |
>0 |
0 |
>0 |
"TEST" |
>0 |
>0 |
<0 |
0 |
CompareOptions.OrdinalIgnoreCase
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
0 |
<0 |
<0 |
"TEST" |
0 |
0 |
<0 |
<0 |
"test" |
>0 |
>0 |
0 |
0 |
"TEST" |
>0 |
>0 |
0 |
0 |
CompareOptions.IgnoreWidth
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
<0 |
0 |
<0 |
"TEST" |
>0 |
0 |
>0 |
0 |
"test" |
0 |
<0 |
0 |
<0 |
"TEST" |
>0 |
0 |
>0 |
0 |
CompareOptions.IgnoreWidth | CompareOptions.IgnoreCase
|
"test" |
"TEST" |
"test" |
"TEST" |
"test" |
0 |
0 |
0 |
0 |
"TEST" |
0 |
0 |
0 |
0 |
"test" |
0 |
0 |
0 |
0 |
"TEST" |
0 |
0 |
0 |
0 |
考察
-
StringComparison.CurrentCulture
では全角半角を区別していないのに、StringComparison.CurrentCultureIgnoreCase
では全角半角を区別しているあたり、直感と異なる動きとなっていて注意が必要です。StringComparison.CurrentCultureIgnoreCase
ではすべてTrue
になると思っていました。
-
CompareOptions.None
では全角半角を区別していないのに、CompareOptions.IgnoreCase
フラグを立てたとたんに全角半角を区別しているあたりもちぐはぐな動きだと思います。
- それ以外は立てたフラグの通りの動作になっているようです。
-
参考先では今回と異なる挙動となっていたことが読み取れます。
現在のカルチャが日本語(ja-JP)の環境で試した限りでは、どのStringComparison列挙体のメンバを使っても、全角文字と半角文字('A'と'A'、'ア'と'ア'など)を区別しないで比較することはできませんでした。
比較結果は.NETのバージョンとかによるのかもしれません。.NET での文字列の比較に関するベスト プラクティスでも
さらに、文字列比較を、異なるバージョンの .NET を使用したり、異なるオペレーティング システムまたはバージョンが異なるオペレーティング システム上の .NET で実行したりすると、異なる結果が返る可能性があります。 詳細については、「Strings and The Unicode Standard」(文字列と Unicode 標準) を参照してください。
とあります。とはいえ今回確認した挙動はUnicodeとかそういう問題じゃない気もしますが…
- InvariantCultureは用途が限定的なので今回はスルーしています
-
CompareOptions
のフラグを見るにつけ、日本語は特別扱いされているというか、頭の痛い言語だなと思います。
まとめ
文字列比較に明示的にオプションを指定するのはプログラマの嗜みの1つですが、それもこう挙動に一貫性でないと苦労します。
仕様をしっかり把握したうえで間違いのないオプションを指定したいですね。
あとテストはちゃんとしましょう。