C#.NET | VB.NET | |
---|---|---|
(Type)value | DirectCast(value, Type) |
基本のキャスト。value の型と Type に継承関係がある場合にキャスト可能。 継承関係ではないが、列挙型とその基になる型の場合、相互にキャスト可能。 C#のみ、下記が可能。
|
× | CType(value, Type) |
VB 系の CInt や CStr を型指定して変換できるようにしたもの。 列挙型と数値型の変換も可能。(規則は数値型同士の変換と同じ) C# の (Type)value と同じく Operator による独自の実装が可能。 ただし、C# の (Type)value の結果と異なることがあり(☆1)、数値型⇔文字列型の変換も可能なことから別物と考えるべき。 |
value as Type | TryCast(value, Type) |
キャスト失敗時に例外発生ではなく、null を返してくれるキャスト。 そのため、Type は null を代入できる参照型となるが、C# のみ、null 許容型も指定可能。 |
☆1 C# の (Type)value と VB の CType(value, Type) の結果が異なるパターン
※全パターン探ってないため、他にもあるかも…
浮動小数点→整数 変換例は★1 |
(Type)value |
0 方向への丸め(切り捨て)。 C や Java のキャストと同じ。 Math.Truncate(value) でも同じ結果だが、型は変えてくれない。 |
---|---|---|
CType(value, Type) |
偶数方向へ丸める四捨五入(銀行丸め)。 Convert.ToInt32(value) と同じ。 Math.Round(value) でも同じ結果だが、型は変えてくれない。 |
★1 浮動小数点→整数の変換例
value | (Type)value | CType | Convert.ToInt32 |
---|---|---|---|
-2.0 | -2 | -2 | -2 |
-1.6 | -1 | -2 | -2 |
-1.5 | -1 | -2 | -2 |
-1.4 | -1 | -1 | -1 |
-1.0 | -1 | -1 | -1 |
-0.6 | 0 | -1 | -1 |
-0.5 | 0 | 0 | 0 |
-0.4 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
0.4 | 0 | 0 | 0 |
0.5 | 0 | 0 | 0 |
0.6 | 0 | 1 | 1 |
1.0 | 1 | 1 | 1 |
1.4 | 1 | 1 | 1 |
1.5 | 1 | 2 | 2 |
1.6 | 1 | 2 | 2 |
2.0 | 2 | 2 | 2 |
VB.NET の DirectCast、CType の使い分け
CType より DirectCast の方がパフォーマンスがいいため、DirectCast 可能な場合は、DirectCast を使う。※ボックス・アンボックス化や、列挙型とその基になる型の相互変換など
String へ変換したい場合は ToString()、String から変換したい場合はそのクラス・構造体の Parse()、TryParse() が大抵使えるので CType は避けるべき。
浮動小数点→整数は、Math のメソッドで丸め後に CType が明示的で分かり易いかも。
整数→整数、整数→浮動小数点は、丸めを気にしなくていいので、素直に CType を使う。
Operator で独自実装している場合は、当然 CType を使用。
VB.NET で C# のキャスト (Double→Integer)
- Math.Truncate を使う方法
Public Shared Function CastToInt(ByVal val As Double) As Integer
Return CType(Math.Truncate(val), Integer)
End Function
- MSIL を使う方法
C# のキャストと同じ結果・挙動になるが、この方法を採るくらいだったら、C# の DLL にキャストメソッドを実装して呼んだ方がまし…
Public Shared Function CastToIntIl(ByVal val As Double) As Integer
Return DirectCast(_castToIntIlInternal.Value.Invoke(Nothing, New Object() {val}), Integer)
End Function
Private Shared _castToIntIlInternal As New Lazy(Of DynamicMethod)(
Function()
Dim instance As New DynamicMethod("CastToIntIlInternal", GetType(Integer), {GetType(Double)}, True)
Dim il = instance.GetILGenerator()
With il
.Emit(OpCodes.Ldarg_0)
.Emit(OpCodes.Conv_I4) 'キャスト処理(オーバーフローチェック無し)に相当
.Emit(OpCodes.Ret)
End With
Return instance
End Function
)
0 件のコメント:
コメントを投稿