VBNMEMO001

BACK

キャスト

CIntとCTypeの仁義なき戦い

VB.NETには例えばDoubleの値をIntegerにしたい場合、2つの方法があります。

  • CInt(Doubleの値) ってする。
  • CType(Doubleの値, Integer) ってする。

速度が違うのかなー、と思ったらそうでもないみたい。

以下、引用。

DirectCastのILコードはunboxでアンボクシング(値型と参照型の変換)だけを行っているようです。CType、CIntの方は変換用のメソッドが呼び出されているよう
です。(中略)少なくともCInt(o)とCType(o , Integer)はILコードレベルでは等価なようです。 

ILコードレベルで等価なら、速度はかわんないだろうなー。

しかしJavaやC#から先にやっている身としては、どうにもCInt()なんてのは気持ち悪いな。 CIntなんてのはVB6時代由来もので、互換性のために(というかプログラマが新しいことを覚えなくていいように?) 残されているような気もするけどなぁ。 うん、特に理由がなければCTypeで書くようにしよう。

DirectCastは守備範囲が狭い!?

CTypeよりもDirectCastの方が速いんですって。

理由は、CTypeが内部的に「VisualBasic.なんちゃらかんちゃら」(「Visual Basic のランタイム ヘルパー ルーチン」とかいうらしい)を使っているのに対して、DirectCastは使っていないかららしい。

じゃあ、CTypeなんか使わずにDirectCastすればいいじゃん! …なんつって、次のようなコードを書くと…

Dim a As Integer = DirectCast(3.14, Integer)

エラーになりますね。

Dim a As Integer = CType(3.14, Integer)

ならOK。

ガッデム、なぜだ!…それは、DirectCastの方が守備範囲が狭いからだそうです。IntegerとかDoubleへはCTypeじゃないと変換できないみたい。

結局、「DirectCastでいけるところはDirectCastで、それ以外はCTypeで」ってのがお利口さんなコーディングスタイルってことでしょうかね。

文字列型の数値への変換

最近知ったんですけど、VB.NETってC#と違ってStringをIntegerにキャストしちゃったりできるんですね。

Option Strict On にしていても関係ないらしい。

Dim a As Integer = CType("123", Integer)
Dim b As Integer = CInt("123")
Console.WriteLine(a + b)

上記を実行すると、エラーにならずにコンソールに「246」と表示されます。

なんとおぞましい。

まあでも、やっぱりInteger.Parse()やらInteger.TryParse()を使った方がいいみたい。 ひとつには動作速度。なんと10倍もParseの方が速いらしい。

参考

2つめには、やっぱ値を厳密に処理してくれることかなぁ。 この点はソースを探すのがめんどくさいのでまた今度。

銀行丸め

こんな記事発見。

  • (VB.Net)DoubleからIntegerへのキャスト時の小数点以下のおかしな挙動。 : 3流プログラマのメモ書き

これは「銀行丸め」ってやつですね!

最近人から教わって知った!

どっちか一方向にばかり丸めると誤差が大きくなって、そりゃカネを扱うシステムにはキケンだってんで、 バランスをとるために「奇数のときは上方、偶数のときは下方」に丸めるという。

これもVB6時代の名残とのこと!

VB.NETでこの手の計算処理を書くときは注意が必要ですね。

最終更新:2013年12月17日 19:20