明示的な変換(キャスト)
キャスト演算子
C# のキャスト演算子 ()
に相当するものは VB.NET にはない。
DirectCast 演算子
-
Object
型とほかの型との変換において、VBランタイムヘルパーを使用しない分、CType
関数より高速に動作する。 - 値型と
Object
型の間の変換にはボックス化、ボックス化解除が使われる。異なる型へはボックス化解除できず、暗黙の型互換があってもInvalidCastException
が発生する。 - 実行時の型が変更後の型と一致しないとキャストに失敗する。たとえば、
Integer
型からString
型へは変換できない。 - C# のキャスト演算子
()
と異なり、暗黙の型互換があっても変換できない。たとえば、Integer
型からLong
型への変換はコンパイルエラーとなる。
TryCast 演算子
- 参照型のみ。
- C# の
as
演算子に相当。IL の isinst 命令 にコンパイルされる。 -
TypeOf ... Is ...
で判定してからDirectCast
するのは変換が二度生じて無駄である。TryCast
してからIsNot Nothing
判定する方がパフォーマンスがよい。
改善前
If TypeOf obj Is T Then
Dim casted = DirectCast(obj, T)
:
End If
改善後
Dim casted = TryCast(obj, T)
If casted IsNot Nothing Then
:
End If
余談
IsNot Nothing
に関し、『コーディング規則 - Visual Basic | Microsoft Docs』に
IsNot の代わりに Not...Is Nothing キーワードを使用します。
とありますが、誤訳ですのでご注意ください。
わざわざ VB2005 で追加したわけだし、「IsNot
演算子の方が否定対象が明確でいいのになあ」と思い、念のため英語ページ をあたったところ、
Use the IsNot keyword instead of Not...Is Nothing.
と全く逆になっていました。
フィードバックすべきか、と思ったらクローズが1件あったので、開いてみると、@tfukumori さんが別の箇所(Handles
と AddHandler
)に関して同様の指摘をされていて、なんと、
現在、機械翻訳されたコンテンツに対する翻訳の問題へのコントリビューションはできません。
という回答で終わっていました。
こんな初歩的・根本的な誤りを放置されるとは…やはり機械翻訳は参考程度に見た方がいいですね。
CType 関数
- Object 型とほかの型との変換において、Microsoft.VisualBasic.CompilerServices.Conversions クラス のようなVBランタイムヘルパーを使用する分、
DirectCast
よりパフォーマンスは落ちる。 - コンパイラによってインライン展開されるため、VBランタイムヘルパーが使用されない場合のパフォーマンスはよい。
- 暗黙の型互換があれば変換できる。暗黙の型互換がない場合、たとえば
Integer
型からDateTime
型への変換はコンパイルエラー、Object
型にボックス化されたInteger
値からDateTime
型への変換は実行時にInvalidCastException
となる。 - VB.NET の
CType
関数と C# のキャスト演算子とでは、結果が異なる場合がある。たとえばSingle
型からInteger
型に変換する場合、CType
関数では小数点以下を銀行型丸め(近い方の整数に、半整数 .5 は偶数になるように丸める)によって取り除くが、C# では切り捨てられる。
データ型変換関数(CStr, CInt, ...)
-
CInt(obj)
とCType(obj , Integer)
は等価(ほかの型についても同様)。 -
CInt
の小数→整数は銀行型丸め。
ヘルパークラス/メソッドによる変換
Parse, ParseExact, TryParse, TryParseExact メソッド
- 文字列から変換。
-
DateTime
型の場合、ParseExact
で書式を明示指定して変換することができる。 -
Nothing
を渡すとArgumentNullException
が発生する。
ToString メソッド
- 文字列化。
-
Enum
のToString()
はメンバ名になる。 -
Decimal
のToString
で末尾のゼロを取り除く(1.0
→"1"
)には、書式"G29"
を指定する。(.NET 1.1 以上の場合)
Convert クラス
- 基本データ型を別の基本データ型に変換する。
- 内部的に
Parse
メソッドを呼んでいる。 - 小数から整数への変換は銀行型丸め。
TypeConverter クラス
- コントロールのデザインプロパティの文字列解析などに使用されている。
-
TypeDescriptor.GetConverter(Type)
メソッドで、実行時に型(Type
オブジェクト)を指定してTypeConverter
オブジェクトを取得することができる。 - 文字列からの変換に
ConvertFromString(String)
メソッドが用意されているが、既定で用意されたコンバーターの許容範囲は狭い。桁区切りカンマ、通貨記号、全角は数値の構成要素として解釈されず、小数から整数へのキャストもできない。
Microsoft.VisualBasic.Conversion.Int メソッド
- 負の値で切り捨てにならない。負でも切り捨てるには
Fix
関数を使う。
Microsoft.VisualBasic.Conversion.Val メソッド
- VB6時代から想定外の挙動で何かと問題を引き起こしてきた。
Val("1,234")
の結果はDouble
の1
である。 - 手軽で許容範囲が広い反面、意図しない変換結果になることがあるので、使用には注意が必要。
暗黙的な変換
暗黙の数値変換(.NET 共通)
- 暗黙的に変換可能な型の対応が「.NET の型変換の表 | Microsoft Docs」に拡大変換/縮小変換と分けて記載されている。
- 拡大変換の多くは情報を失うことなく実行できるが、浮動小数点数値型への変換では精度が損なわれるケースもある。
- 縮小変換では情報が失われる可能性がある。変換元の値が変換先の型の
MaxValue
とMinValue
の範囲外にある場合はOverflowException
が発生する。 -
Integer
のリテラル、定数値が変換先の型の範囲内にある場合、暗黙的に変換できる。範囲外の場合はコンパイルエラーとなる。
Option Strict Off
- Off だと意図しない型変換が暗黙的に行われ、バグの温床になる。On にすることが推奨されている。
- 既定は Off なので、プロジェクトを作成したら [コンパイル オプション] 設定で On にするのを忘れないようにする。
- たまに忘れて後で気づく。VB6からの移行を考慮してのことなのかもしれないが、そろそろプロジェクトの既定は On に変えてほしい。