VB.NETでも等値演算子で文字列を比較したい

言い訳

もしかしたら生粋のVBプログラマなら常識的なことなのかもしれませんが、等値演算子『=』(で呼び方あってますよね?)で文字列を比較するときに空文字とNothingの比較でつまずいたのでそれのメモ。

なんで違う?

以下のC#VB.NETのコードを見て、実行結果を同じと思いますか? それとも違うと思いますか?

string str1 = "";
string str2 = null;

// false
Console.WriteLine(str1 == str2);
// false
Console.WriteLine(str1.Equals(str2));
Dim str1 As String = ""
Dim str2 As String = Nothing

' True
Console.WriteLine(str1 = str2)
' False
Console.WriteLine(str1.Equals(str2))

コメントで答えを書いちゃっているんですけど結果が違うんです。

等値演算子を使ってる方はC#は期待通りの答えを返してくれるのになんでVB.NETNothing""であからさまに違うものを等しいと評価しているでしょうか。どちらも演算子オーバーロードされているメソッドを呼び出してるんじゃないんですか?

意味ワカンネ。

出、出〜www IL逆変換奴〜www

まぁ、逆アセンブラにでも突っ込めばそれぞれ何のメソッドを呼び出しているか分かるでしょう。 そういう事でぶち込んでみたところ、それぞれ違うメソッドを呼び出していることが分かりました。

C#の方はSystem.String::op_EqualityVB.NETMicrosoft.VisualBasic.CompilerServices.Operators::CompareStringを呼び出しているようです。

Operators::CompareString? 知らない子ですね。

Operators.CompareString メソッド (String, String, Boolean) (Microsoft.VisualBasic.CompilerServices)

説明を読む限り、VB.NETコンパイルオプションのOption Compareを実現するためにコンパイル時にこいつに置き換えているみたいです。 Option Compareの値によって比較方法を変えるためにこいつに置き換えてからbinarytextかで第三引数の値を当てはめているみたいです。

アセンブリを読む限り、『=』で比較されたらCompareStringで比較して返り値を0と等しいかを比較し、その値を返しているみたいです。

んで、CompareString""Nothingを同じ値と見なしていると。

何ででしょう? レガシーVBとの互換性の為ですか?

ドキュメントを大切に

あと、この記事を書くために調べて気が付いたのですが、この事はフツーにmsdnの注意書きに書いてありました。

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

この件から私が得る教訓は、VB.NETで不可解な事があってもいきなり検証コードを書き始めたり逆アセンブルを行う前に関連するであろうmsdnドキュメントには一通り目を通しておくべきだと言うことだ。