【C#】大文字小文字を区別せずに文字列比較

C#

こんにちは、働くC#プログラマーのさんさめです。

C#で文字列比較をするのは、
特に難しいことはありません。

普通に比較演算子「==」で比較すれば
一致かどうか確認できます。

var str = "Hoge";
if (str == "Hoge")
{
    // True! ここには入ってくる
}

ところが、
「==」で結ぶやり方では、
「Hoge」と「hoge」のように、
大文字小文字が異なるだけの文字列は
不一致とみなされます。

var str = "Hoge";
if (str == "hoge")
{
    // False…ここには入ってこない
}

大文字小文字を区別せずに文字列を比較したい場合は、
Equalsメソッドと、その引数である
StringComparison.OrdinalIgnoreCaseを使えばOKです。

string.Equals("Hoge", "hoge", StringComparison.OrdinalIgnoreCase);

え?両方ToUpper
して比較すれば良いんじゃ…

もちろんそれでも良いです。

ただ、今回紹介する方法を使った方が、
ToUpperやToLowerを使うよりもシンプルに記述できます。
詳しく解説していきます。

スポンサーリンク

string.EqualsにOrdinalIgnoreCaseを指定して比較する

string.Equalsには、
文字列の比較規則を指定できるオーバーロードがあります。

の2つです。

この第2引数(静的メソッドの場合は第3引数)に、
OrdinalIgnoreCaseを指定することで、
大文字小文字を区別せずに比較を行うことができます。

具体的なサンプルコードです。

var a = "Hoge";

// ↓はfalse。「==」では大文字小文字を区別する
Console.WriteLine(a == "hoge"); 

// ↓はtrue。OrdinalIgnoreCaseを指定すると
// 大文字小文字を区別しない
Console.WriteLine(a.Equals("hoge", StringComparison.OrdinalIgnoreCase));

// ↓もtrue。静的メソッドを使う場合の書き方
Console.WriteLine(string.Equals(a, "hoge", StringComparison.OrdinalIgnoreCase));

多少記述量は増えますが、
大文字小文字を区別しないで比較したい時は、
これだけで大丈夫です。

わざわざ関数を自作しなくて良いということですね。

ちなみに、OrdinalIgnoreCase以外にも、
「なんたらIgnoreCase」が2つほどありますが、
どちらも日本では使いません

しかも、他2つは無駄に処理も重くなってしまいます。

  • 大文字小文字を区別したいならOrdinalIgnoreCase
  • そうでないなら普通に「==」で比較

と覚えておけば充分です。

静的メソッドなら絶対にnull参照例外にならないのでオススメ

さて、先ほど述べたようにstring.Equalsには
インスタンスメソッドと、
静的メソッドがあります。

結果が同じなんだから、
どっちを使っても良いよね?

いいえ、そんなことはありません。
絶対に静的メソッドの方を使った方が良いです。

なぜなら、インスタンスメソッドの方は、
null参照例外になる可能性があるからです。

先ほどのコードを少し変えて、
変数aにnullを入れてみましょう。

string a = null;

// ↓はfalse。大文字小文字は区別できないが安全
Console.WriteLine(a == "hoge"); 

// ↓は例外。aがnullなのでNullReferenceExceptionになる
Console.WriteLine(a.Equals("hoge", StringComparison.OrdinalIgnoreCase));

// ↓はfalse。大文字小文字を区別しつつ安全

そして実行すると…

この通り、例外になってしまいました。

このように、インスタンスメソッドを使った場合は、
そのインスタンスがnullの時に例外になってしまいます。

どんな値が来るか分からない場合、
安全のために静的メソッドの方を使いましょう。

OrdinalIgnoreCaseが使える他の関数

OrdinalIgnoreCaseの指定は、
Equalsメソッド以外にも
以下の関数で使えます。

  • StartsWith
  • EndsWith
  • IndexOf
  • LastIndexOf
  • Contains
  • Compare(静的メソッド)

文字列比較ができるメソッドは、
ほとんど対応していることになりますね。

逆に、以下のメソッドでは指定ができません。

  • Split
  • CompareTo
    • ただし、静的メソッドのCompareを使えばよい

Splitの分割に使う文字列の指定で、
大文字小文字を区別しないようにするときは、
「a」と「A」両方を指定する必要があるということですね。

とはいえ、Splitの分割に使う文字には、
多くの場合「 (半角スペース)」や「,」など、
アルファベット以外を指定することがほとんどなので、
日常で困ることはほぼないでしょう。

Dictionaryのキーに使う場合はToUpperなどを使うしかない

単純な文字列の比較であれば、
大文字小文字を区別しないためには、
StringComparison.OrdinalIgnoreCaseを
使えばよいことを説明しました。

ところが、Dictionaryのキーとして文字列を使い、
なおかつ大文字小文字を区別したくない場合は、
この指定を使うことはできません。

そのため、そのような使い方をしたい場合には、
あらかじめToUpper(Invariant)を呼んで
正規化しておく必要があります。

サンプルコードです。

var dic = new Dictionary<string, string>();
dic.Add("hoge", "Foo");

// ↓はfalse。
Console.WriteLine(dic.ContainsKey("Hoge"));

// 辞書のキーで大文字小文字を区別したくない場合は、
// あらかじめToUpperなどで揃えておく必要がある
dic.Add("fuga".ToUpperInvariant(), "Bar");
// ↓はtrue
Console.WriteLine(dic.ContainsKey("Fuga".ToUpperInvariant()));

ToUpperInvariantは
.NET の文字列を使用するためのベスト プラクティス
に書かれているように、
OrdinalIgnoreCaseを指定したときに
内部処理で使われているメソッドです。

ただ、ここ日本では、
別にToUpperを使っても問題ありません。

記述量も増えるので、
私はこのようなケースでも
ToUpperしか使っておりません。

まとめ

まとめです。

  • 文字列の大文字小文字を区別しないで比較するには、
    string.Equalsと、
    StringComparison.OrdinalIgnoreCaseを使う
  • ContainsやEndsWithなど
    文字列比較が絡むメソッドでは大体使える
  • 辞書のキーで大文字小文字を区別したくない場合は、
    あらかじめToUpperなどで揃えておく必要がある

最後までお読みいただき、ありがとうございました。

関連記事

関連記事です。

大文字小文字を区別したくない
…の最たるものがファイルパスでしょう。
ただし、ユーザーに情報を見せる必要があるときは、
大文字小文字が正確な方が良いですね。

大文字小文字を区別してファイルパスを取得する
で紹介している方法を使えば、それが実現できます。

コメント

タイトルとURLをコピーしました