CType vs. Parse

If I had a form where I wanted to add together two numbers entered as text by the user -- so it becomes necessary to convert the text properties of the textboxes to decimal values -- which approach is better?
1: Total = CType(Me.TextOne.Text, Decimal) + CType(Me.TextTwo.Text, Decimal)
OR
2: Total = Decimal.Parse(Me.TextOne.Text) + Decimal.Parse(Me.TextTwo.Text)
Thoughts?Smile
[497 byte] By [MadGerbil] at [2007-12-16]
# 1
I started to say...
"Well, it depends upon how much you trust the data, and what you're willing to sacrifice in performance for better checking."
Then I thought I would do some performance checking so that I'd have actual data. Turned out the empirical evidence didn't agree with my initial thoughts.
Take the following example:


Imports System
Imports System.Globalization
Imports Microsoft.VisualBasic
Module DecimalParseDemo
Public Enum CastType
Parse
[CType]
[DirectCast]
End Enum
Public Function DecimalParse(ByVal castType As CastType) As Integer
Dim errorCount As Integer = 0
Dim decimalFormats As String() = { _
"9876543210.9876543210", "9876543210,9876543210", _
"(9876543210,9876543210)", _
"9,876,543,210,987,654.3210", _
"9.876.543.210.987.654,3210", _
"98_7654_3210_9876,543210"}
Dim decimalString As Object
For Each decimalString In decimalFormats
Dim decimalNumber As Decimal
Try
Select Case castType
Case DecimalParseDemo.CastType.Parse
decimalNumber = Decimal.Parse(decimalString)
Case DecimalParseDemo.CastType.CType
decimalNumber = CType(decimalString, Decimal)
Case DecimalParseDemo.CastType.DirectCast
decimalNumber = DirectCast(decimalString, Decimal)
End Select
Catch ex As Exception
errorCount = errorCount + 1
End Try
Next decimalString
Return errorCount
End Function
Sub Main()
Dim finish As Date
Dim start As Date
Dim errorCount As Integer
errorCount = 0
start = Date.Now
For i As Integer = 1 To 1000
errorCount = errorCount + DecimalParse(CastType.Parse)
Next
finish = Date.Now
Console.WriteLine("Time to do 6000 Decimal.Parses = " & finish.Subtract(start).ToString())
Console.WriteLine("Decimal.Parse reported " & errorCount & " error(s).")
errorCount = 0
start = Date.Now
For i As Integer = 1 To 1000
errorCount = errorCount + DecimalParse(CastType.CType)
Next
finish = Date.Now
Console.WriteLine("Time to do 6000 CTypes = " & finish.Subtract(start).ToString())
Console.WriteLine("CType reported " & errorCount & " error(s).")
errorCount = 0
start = Date.Now
For i As Integer = 1 To 1000
errorCount = errorCount + DecimalParse(CastType.DirectCast)
Next
finish = Date.Now
Console.WriteLine("Time to do 6000 DirectCasts = " & finish.Subtract(start).ToString())
Console.WriteLine("DirectCast reported " & errorCount & " error(s).")
End Sub
End Module


My output was:
Time to do 6000 Decimal.Parses = 00:00:07.4807568
Decimal.Parse reported 3000 error(s).
Time to do 6000 CTypes = 00:00:13.0988352
CType reported 2000 error(s).
Time to do 6000 DirectCasts = 00:00:14.1603616
DirectCast reported 6000 error(s).
This output was very surprising to me. Initially I expected DirectCast to be the fastest, but apparently since Decimal doesn't inherit from String, it just throws an exception and can't parse any of the items. Exception handling is always slow, so that bumps it up to the slowest, so that made sense to me once I thought about it.
However, the differences between Parse and CType are still somewhat surprising. Parse reported more errors, which I expected, but it was also faster, in spite of reporting more errors, which I didn't expect at all. So, given this data sample, Parse seems to be the way to go, but in the lnog run, it may depend upon your data.
I ran this test several times. Sometimes DirectCast was the slowest, and sometimes CType. Decimal.Parse was always the fastest.
ChrisJ.Breisch at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 2
That is probably the most thorough answer I've ever gotten to any question in my life.

Thanks.

MadGerbil at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 3

Heh!

But do you regret asking it? I don't regret reading it.

GerardL at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 4

It is a good question. Good job.

Remember to make sure you validate your inputs just in case :-p

ahmedilyas at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 5
Faster still is Decimal.TryParse, as you don't use the catch block.

if decimal.tryparse(decimalString, decimalNumber) = false then
errorcount += 1
end if

Time to do 600000 Decimal.Parses = 00:00:25.5467344
Decimal.Parse reported 300000 error(s).
Time to do 600000 CTypes = 00:00:48.9203440
CType reported 200000 error(s).
Time to do 600000 DirectCasts = 00:00:49.6113376
DirectCast reported 600000 error(s).
Time to do 600000 DecimalTryParses = 00:00:00.4606624
DecimalTryParse reported 300000 error(s).
Press any key to continue . . .

The catch block is VERY demanding!! Mind you, for validating textboxes you are not going to notice the performance difference (unless the users are cylons).

jo0ls at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...
# 6

true

remember any exception is expensive - especially the general Exception itself but makes it better to use a specific exception type however still expensive

sorry, going OT here... shouldnt!

but yes, learnt a couple of things here....

ahmedilyas at 2007-9-9 > top of Msdn Tech,.NET Development,.NET Base Class Library...

.NET Development

Site Classified