Reputation: 122
I am using IsNumeric()
function in my code to validate numbers.
IsNumeric(100)
- true,
IsNumeric(-100)
- true,
IsNumeric(+100)
- true,
IsNumeric(100-)
- true - I have doubt in this. (100-) Is this a valid number? IsNumeric () returns true to this value.
Dim latitude As String = "12.56346-"
If IsNumeric(latitude) Then
If (Convert.ToDouble(latitude) >= -90 And Convert.ToDouble(latitude) <= 90) Then
isValidLatitude.Text = "true"
Else
isValidLatitude.Text = "false"
End If
Else
isValidLatitude.Text = "false"
End If
Error while converting latitude
to double
Input string was not in a correct format.
Upvotes: 2
Views: 1182
Reputation: 4424
Note: my previous answers were wrong about assuming it was a bug. As the answer of @Damien_The_Unbeliever states, this function tries to validate the string as a lot of data types. And actually, the value "100-"
is a valid Decimal
number. That's why it returns true (as it's a "valid" Decimal) but gives a exception when converting to Double (as it's not a valid Double). @Damien_The_Unbeliever really deserves your +1 for pointing that.
From the documentation (showing all the data types that IsNumeric tries to validate):
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number. Expression can contain non-numeric characters. IsNumeric returns True if Expression is a string that contains a valid hexadecimal or octal number. IsNumeric also returns True if Expression contains a valid numeric expression that begins with a + or - character or contains commas.
Also, @CaiusJard did a nice search and pointed out that inner methods use a NumberStyles.AllowTrailingSign
option, which allows this behavior.
Ok, now to the solution:
Just use a TryParse
method, from your desired data type (int
, long
, etc...). The cool thing is that it'll behaves exactly as you expect, and if the parsing is successful, we have the parsed value already available to use!
if (Int32.TryParse(value, out int number))
{
// String is a valid number, and is already parsed in the 'number' variable!
}
else
{
// String is not a valid number!
}
Solution's VB.Net version:
Dim value As String = "12.56346-"
Dim number As Double = 0
If Double.TryParse(value, number) Then
' String is a valid number, and is already parsed in the "number" variable!
isValidLatitude.Text = "true"
Else
' String is not a valid number!
isValidLatitude.Text = "false"
End If
Upvotes: 3
Reputation: 74660
IsNumeric
is from the Microsoft.VisualBasic namespace/dll, a bunch of helper stuff intended to help VB6 programmers get their arcane VB6 code /knowledge working on VB.NET
You'll note if you use other functions from the same dll such as Microsoft.VisualBasic.Conversion.Int()
, or you use dedicated VB.NET converters such as CInt
or CDbl
these will also cope with a trailing minus sign and return a negative value
If you want to dispense with the old ways of VB6, use a numeric type's TryParse.. but all in, be consistent / if you use a function from Microsoft.VisualBasic to determine if a conversion can be made, use the vb conversion because within itself the package will be consistent but between Microsoft.VB and normal .net System there are some differences in behavior
Edit:
A couple of people have been wondering about the source code and how it uses TryParse, so why doesn't it work like using TryParse directly?
Microsoft.VisualBasic.Information.IsNumeric()
uses Microsoft.VisualBasic.CompilerServices.DoubleType.TryParse()
to determine whether an expression is numeric. This DoubleType.TryParse
is not the same as Double.TryParse
- it is a helper method again in the VB namespace that specifically sets the NumberStyles.AllowTrailingSign
flag among many other flags. When parsing the number (first as non currency related, using Double.Parse, then if it fails a second attempt is made using adjusted values for currency related tests) this AllowTrailingSign flag will be considered in conjunction with other regional number formatting rules in determining if the passed in value is numeric
You'll note that on a machine obeying a USA number formatting culture, a string of "(100$)" is also declared to be numeric but calling Double.TryParse("(100$)", x)
will also return false. The VB helper methods here are being a lot more liberal in what they accept than the System methods, because they're telling the System methods to be more liberal than they are by default
As noted, I've always regarded the Microsoft.VisualBasic namespace as a bunch of helper methods intended to allow terrible old VB6 code to be pasted into VB.NET and work with minimal fiddling. I wouldn't advocate using it for new projects and I remove the reference when I work on VB.NET - using it to support the VB6 notions of "just sling anything in, of any type, and it'll probably figure it out and work.. and if it doesn't we can always on error resume next" should be discarded in favour of precise and accurate about the operations executed and their intent
Upvotes: 7
Reputation: 239764
IsNumeric
answers a question no sane person wants to ask. As quoted by Vitox's answer:
IsNumeric returns True if the data type of Expression is Boolean, Byte, Decimal, Double, Integer, Long, SByte, Short, Single, UInteger, ULong, or UShort. It also returns True if Expression is a Char, String, or Object that can be successfully converted to a number.
Note, it doesn't tell you that the given string can be converted to all numeric types. It tells you that the string can be converted to at least one numeric type. And for bonus bad style points, of course, it doesn't tell you which types the string can be converted to.
Decimal.Parse("100-")
will execute perfectly well and give you a Decimal
containing a value of -100.
So, it's not a bug, it's a bad function that has been retained for backwards compatibility reasons. Nowadays, we know better, and that we want to test whether a string can be converted to a specific data type, for which the TryParse
family of functions have been designed.
Upvotes: 3