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 : 【 12345】00:00:00.0023815
- Convert.ToInt32 : 【 12345】00:00:00.0030900
- Int32.Parse : 【 12345】00:00:00.0468925
- 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
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)
-
-
- list.Sort(AddressOf hikaku)
- Return list
- End Function
- End Class
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