明示的な変換(キャスト)
キャスト演算子
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 に変えてほしい。