読者です 読者をやめる 読者になる 読者になる

nakamurakko’s diary

プログラマー

C# 文字列比較

  • ググった

C#の文字列比較はどの方法が良いのか分からなかったので、「C# 文字列比較」で検索すると、上位に出てくるのがケース1~3だった。

 

ケース1

  1. string stringValue = "0";
  2. int intValue = 0;
  3.  
  4. // stringとintを==演算子で比較するとビルドエラーになる。
  5. System.Console.WriteLine(stringValue == intValue);

「等値演算子で比較すればビルドエラーになるから、実行前に発見出来る」というのをネットで見かけた。そして、その多くは「で、ビルドエラーはどのように対処するのか」が抜けていた。

 

ケース2

  1. string stringValue = "0";
  2. object objectValue = "0";
  3.  
  4. System.Console.WriteLine(stringValue == objectValue);

 

ケース3

  1. string stringValue = "0";
  2. object objectValue = 0;
  3.  
  4. System.Console.WriteLine(stringValue == objectValue);

 

ケース2~3は、ボックス化してしまえば、intとstringは比較出来てしまい、ケース1のように等値演算子だけでは抜けがあるというのを示している。
これもネットで見かけたけど、どうすれば良いのかという答えにはならないかな。モヤッとしたまま。

  • MSDNライブラリを確認

そもそもstringとは?と思ってMSDNライブラリで調べてみた。

string (C# リファレンス)

比較的最初の方でこのように書いてある。

string は参照型ですが、等値演算子 (== および !=) は、string オブジェクトの参照ではなく、値を比較するように定義されます。

 

 そして、下記のサンプルコードが付属している。 

  1. string a = "hello";
  2. string b = "h";
  3. // Append to contents of 'b'
  4. b += "ello";
  5. Console.WriteLine(a == b);
  6. Console.WriteLine((object)a == (object)b);

実行してみるとstring同士での比較(5行目)はTrue、object型にキャストしたstring同士の比較(6行目)はFalseになる。

string(System.Stringクラス)は、等値演算子で比較した場合、違うオブジェクトでもTrueと判定してくれるという事だ。

 

  • 何故、等値演算子で 比較出来るのか?

「オブジェクトの比較だと思っていたのに、文字列自体を比較してくれるのは何故か」と気になって調べていたら、このページを見つけた。

String.Equality 演算子 (String, String) (System)

 stringは等値演算子オーバーロードをしていて、解説にはこう書いている。

The operator, in turn, calls the static Equals(String, String) method, which performs an ordinal (case-sensitive and culture-insensitive) comparison.

(大文字小文字を区別し、カルチャーに依存しない比較を行う、staticのEquals(String, String)を呼び出します。)

 

つまり、下記4行目と5行目は同じという事になる。

  1. string stringValue1 = "0";
  2. string stringValue2 = "0";
  3.  
  4. System.Console.WriteLine(stringValue1 == stringValue2);
  5. System.Console.WriteLine(string.Equals(stringValue1, stringValue2));

 

  • 結論

上記を踏まえて、

  1.  文字列比較する時はToStringなどで型を合わせてから行う。
    (ビルドエラーで云々とか言わないで型を合わせる。当たり前だけど。)
  2. 等値演算子String.Equals メソッド (String, String) (System)を呼び出しているので使用して構わない。
    (String.Equals メソッド (String) (System)のどちらを使うかはプロジェクトごとに決めるのが良いかも。)

という、個人的な結論に至った。

 

  • 補足

String.Equality 演算子 (String, String) (System)のメモには、こんな事が書いてあった。

The Visual Basic compiler does not resolve the equality operator as a call to the Equality method.

(Visual Basic コンパイラは等値演算子で Equality メソッドを呼び出しません。)
The operator, in turn, calls the static Equals(String, String) method, which performs an ordinal (case-sensitive and culture-insensitive) comparison.

(代わりに、 Operators.CompareString メソッドが呼ばれます。)

VBでは等値演算子で呼ばれるのはString.Equalityではなく、Operator.CompareStringを呼び出しているという事だ。

  1. Option Compare Text
  2.  
  3. Class Program
  4.     Public Shared Sub Main()
  5.         Dim stringValue1 As String = "aaa"
  6.         Dim stringValue2 As String = "AAA"
  7.  
  8.         System.Console.WriteLine(stringValue1 = stringValue2)
  9.         System.Console.WriteLine(stringValue1.Equals(stringValue2))
  10.     End Sub
  11. End Class

 「Option Compare Text」が、ソースまたはプロジェクトに宣言してある状態で等値演算子で比較すると、大文字小文字の違いがあってもTrueが返ってきてしまう(8行目)。

VBを知っていれば当然といえば当然の事だろうけど、C#と同じ感覚でコードを書いてしまうとハマってしまうかもしれない。