2012年07月01日

C#で文字列の比較(Equals関数または==記号)

今回はC#で文字列が等しいかどうかを判断する方法について考えてみます。


どっちがいいの?
string a = "";
string b = "";

if (a.Equals(b))
{
//Equals関数を使う?
}

if (a == b)
{
//==記号を使う?
}



いきなり結論


基本的に動作はほとんど同じだが、両方の性質をよく理解し、使い分けるべきところでは使い分ける。どちらでもいい場合はどちらを使ってもよい。ただしプログラム全体でどちらを使うか統一したほうがよい。

いきなり結論です。とても玉虫色です。玉虫色の結論を導く玉虫色の根拠を以下からどうぞ。


パフォーマンスについて


何はともあれパフォーマンスです。内部的に、==記号はEquals関数を呼んでいます。なので理論的にはEquals関数のほうが有利です。が、その差は微々たる物。何億回も呼び出すのでなければ気にすることもないでしょう。


見やすさ、書きやすさ


見やすさについては個人差もあると思いますが、==記号が有利でしょうか。書きやすさについても==記号に軍配ですね。キーを押す回数が違いますし、Equals関数はShiftキーを押さなきゃいけないのがなんとも。Intelli Senseを用いても覆りません。


お作法


.NETの参照型においては、==記号は参照の比較、Equals関数は値の比較を行うというお作法があります。
Equals() と演算子 == のオーバーロードに関するガイドライン (C#)
Stringクラスは参照型で、普通、文字列が等しいかどうかは調べるときは値を比較します。なのでEquals関数を使うべきです。ですが、Stringクラスは特別で、==記号も値を比較するようオーバーライドされています。即ちMicroSoftが==記号を使ってよいと言っているということ。お作法の話はEquals関数を使うべきという根拠にならない、ってことになりますね・・・。

ちなみにJavaではEquals関数を使うべきです。これはもう絶対です。プログラム界の一大勢力であるJavaと合わせるのはいいことですよね。「よそはよそ、うちはうち」とも言えますが・・・。


タイプセーフ


==記号を使う根拠に、タイプセーフであるということがあります。


intとstringを比較
int i = 0;
string s = "0";

if (i.Equals(s))
{
//falseになります。
}

if (i == s)
{
//intとstringを比べられないってことでビルドエラーです。
}

上記のようなコードを書いてしまったとき、==記号のほうが間違いに気づきやすくていいじゃん、ってこと。確かにそのとおり。では以下のような例ではどうでしょうか?


object型がからむと・・・?
string s1 = new string(new char[] { 'a', 'b', 'c' });
string s2 = new string(new char[] { 'a', 'b', 'c' });
object o1 = s1;

if (o1 == s2)
{
//falseになります。
}

if (o1.Equals(s2))
{
//trueになります。
}

変数o1とs2にはともに"abc"という同じ文字列が入っています。なのに結果が違いますね。おそらく普通はtrueになってほしいはず。この場合、とても気づきにくいバグになってしまいます。


NULLの場合は?


NULLが絡んだ場合は==記号のほうが有利でしょうか。


変数がNULLNの場合
string s1 = null;
string s2 = null;

if (s1 == s2)
{
//trueになります。
}

if (s1.Equals(s2))
{
//NullReferenceExceptionで落ちます。
}

==記号はNULLでも気にせず比較できます。ですが、「プログラムにおいてNULLチェックは基本。NULLチェックしないのは便利ではなくただの堕落だ。」とも言えます。無理矢理すぎか・・・。一応、比較の片方がNULLでないことがわかってるなら、前に持ってくることでNULLチェックをサボれます。これもまた基本中の基本ですかね。


片方がNULLでないとわかってる場合
string s = null;

if ("abc" == s2)
{
//falseになります。
}

if ("abc".Equals(s))
{
//falseになります。
}



あとがき


今回はあえて結論をどちらにも倒さないように書いてみました。色々考えていくと、「こっちを使え」、「あっちを使うな」って言えるほど単純ではないと思うのです。個人的にはJavaみたいにどちらかで確定してほしいです。例え少しくらい不便でも、です。






ラベル:C# .net
posted by ぺるたご at 23:14| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。