ページ

2005年3月25日金曜日

3f.Equals(3) は true か?

C# and Equals() in V2.0 versus V1.0. より


以下、要点だけ書いてみます。


3f.Equals(3) は true なのかどうか。
わかりにくいかもしれませんが、3f っていうのは float の 3.0 のことですから、3f.Equals() っていうのは System.Single 構造体の Equals メソッドを呼び出すってことになります。引数の 3 は当然 int、すなわち System.Int32 です。Equals メソッドの引数は object ですから System.Int32 が box 化されて渡されます。Equals メソッドは型が違えば false を返しますから、当然 3f.Equals(3) の結果は false です。


というのは .NET Framework 1.x での話。
2.0 では System.Single 構造体の Equeals メソッドは Equals(object) と Equals(float) の 2つが用意されています(Single.Equals Method 参照)。そして、C# 2.0 コンパイラは box 化が不要な Equals(float) を呼び出すようにコンパイルします。int 3 は float に暗黙に変換できますから特に問題はありません(暗黙の変換については C# 言語仕様 「6.1.2 暗黙の数値変換」 参照)。すると 3f.Equals(3) は 3f.Equals(3f) と同等とみなされることになり、結局 true を返します。


では、3.Equals(3f) はどうでしょう?
2.0 では System.Int32 にも Equals(object) と Equals(int) が用意されています(Int32.Equals Method 参照)。しかし、引数の 3f (float 型)を暗黙に int に変換することは許されていません。そのため box 化して Equals(object) を呼び出すコードが生成されます。ですから、結果は false となります。


。。。ってことが書いてあると思うんだけど。。。
これってほんとにいいんだろうか?たぶん、Single.Equals() に object 版と float 版を用意するのは 「box 化を不要にすることによって (場合によっては) パフォーマンスを向上できる」 ということなんだろうけど。。。
けど、いろいろと気持ち悪いなぁ。それに
Equals および等値演算子 (==) 実装のガイドライン
Equals メソッドの実装
これらのガイドラインを破りまくることにもなるし。。。


最後の一文 「Let us know if you find an interesting counter-example where this change could cause grief!」。これは 「この変更で何かまずいことが起こる例を見つけたら教えて」 てな感じでいいのかな?ということは、中の人も 「ベストじゃないかもしれないけど、メリットもあるからこうしたいなぁ」 って考えてるってことかな?

0 件のコメント:

コメントを投稿