VB.NET/.NetFramwork2で型変換の速度差、特色について気になりだしたので、実験してみました。
興味があった変換は、普段よく使う
- Object→Int32への変換
- String→Int32への変換
です。
実験したものはCtype、CInt、DirectCast、Convert.ToInt32、Int32.Parse、 Int32.TryParse。
実験結果としてはこんな感じです。【 】の中の数値はObjectなりStringなりのmyData変数を、それぞれのメソッドなりでの変換したものです。Int32.TryParseで【 0】となっているのは、変換できなかったということですね。
実験結果
(速度の早い順に並び替え)
Dim my_Data As Object = 12345
DirectCast : 【 12345】00:00:00.0004363
CInt : 【 12345】00:00:00.0023329 'CtypeとCInt、Convert.ToInt32は順位が入れ替わるときがあります。
CType : 【 12345】00:00:00.0023815
Convert.ToInt32 : 【 12345】00:00:00.0030900
Int32.Parse : 【 12345】00:00:00.0468925 'Int32.ParseとInt32.TryParseは順位が入れ替わるときがあります。
Int32.TryParse : 【 12345】00:00:00.0475714
Dim my_Data As Object = 12345.5
CInt : 【 12346】00:00:00.0039555
CType : 【 12346】00:00:00.0040038
Convert.ToInt32 : 【 12346】00:00:00.0052587
Int32.TryParse : 【 0】00:00:00.0631435
Dim my_Data As String = "12345"
Int32.Parse : 【 12345】00:00:00.0198393
Int32.TryParse : 【 12345】00:00:00.0206115
Convert.ToInt32 : 【 12345】00:00:00.0214960
CType : 【 12345】00:00:01.7970309
CInt : 【 12345】00:00:01.7990923
Dim my_Data As String = "12345.5"
Int32.TryParse : 【 0】00:00:00.0198050
CInt : 【 12346】00:00:01.8433437
CType : 【 12346】00:00:01.8474300
所感としては、Object型のときは、DirectCastを使うのが一番高速(但しDirectCastは丸め処理などは行わず、Int32に変換するのに小数などを引数に渡すとエラーを吐きます)。String型のときは、Int32.Parseが一番高速…、というところでしょうかね。現実問題としてはInt32.TryParseも、使い勝手がよさそうです。
サンプルソース
▲TextBox1に結果が出るわけです…。
※Int32.Parseの引数はもともとString型なので、Option StrictはOffにしないと走りません。
Imports System.Diagnostics
Public Class Form1
Private Sub Button1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim sw As New Stopwatch
Dim sb_Data As New System.Text.StringBuilder
Dim bl_result As Boolean
Dim my_Dict As New Dictionary(Of String, String)
Dim my_Data As Object = 12345 '#---ここをあれこれ差し替えました。
' 少数の値をセットしたりして
' エラーができるときは、
' 型変換部分も
' コメントアウトします。
Dim int_Data As Int32
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
int_Data = CType(my_Data, Int32)
Next
sw.Stop()
my_Dict.Add("CType" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
int_Data = CInt(my_Data)
Next
sw.Stop()
my_Dict.Add("CInt" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
int_Data = DirectCast(my_Data, Int32)
Next
sw.Stop()
my_Dict.Add("DirectCast" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
int_Data = Convert.ToInt32(my_Data)
Next
sw.Stop()
my_Dict.Add("Convert.ToInt32" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
int_Data = Int32.Parse(my_Data)
Next
sw.Stop()
my_Dict.Add("Int32.Parse" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
sw.Reset()
sw.Start()
For i As Int32 = 0 To 100000
bl_result = Int32.TryParse(my_Data, _
int_Data)
Next
sw.Stop()
my_Dict.Add("Int32.TryParse" & vbTab _
& int_Data.ToString, _
sw.Elapsed.ToString)
'----------------------------------
Dim sorted As List(Of KeyValuePair(Of String, String)) _
= sortByValue(my_Dict)
sorted.Reverse()
For Each kvp As KeyValuePair(Of String, String) In sorted
Dim str_SPL() As String _
= kvp.Key.Split(vbTab.ToCharArray)
Dim str_Num As String _
= Strings.StrDup(10, " ") & str_SPL(1)
sb_Data.Append((str_SPL(0) & " :" _
& Strings.StrDup(20, " ")).Substring(0, 20) _
& "【" & (str_Num).Substring(str_Num.Length - 10, 10) & "】" _
& kvp.Value & vbCrLf)
Next
Me.TextBox1.Text = sb_Data.ToString
sb_Data.Remove(0, sb_Data.Length)
sb_Data = Nothing
End Sub
Shared Function hikaku(Of TKey, TValue As IComparable(Of TValue))( _
ByVal kvp1 As KeyValuePair(Of TKey, TValue), _
ByVal kvp2 As KeyValuePair(Of TKey, TValue)) As Integer
Return kvp2.Value.CompareTo(kvp1.Value)
End Function
Shared Function sortByValue(Of TKey, TValue As IComparable(Of TValue))( _
ByVal dict As Dictionary(Of TKey, TValue)) _
As List(Of KeyValuePair(Of TKey, TValue))
Dim list As New List(Of KeyValuePair(Of TKey, TValue))(dict)
'Valueの大きい順にソート
list.Sort(AddressOf hikaku)
Return list
End Function
End Class