This is not a true article, it is just a tip about a "trap" that I discovered in the VB.NET
IsNumeric() function and that I need to share with the VB programmers community.
If you used VB6 in the past especially, you would know that the
IsNumeric() function is able to determine if a given string is convertible to a number or not. Of course, VB.NET also supports it, as it supports many other legacy VB functions (by referencing Microsoft.VisualBasic.dll). These functions should all be avoided in favor of the .NET Framework counterparts, however many VB programmers still use them. That's why I think it's important you are aware of this trap.
Let's start with this line of code:
Honestly, do you think it will ever return "
False"? No, it always returns "
True", doesn't it? Well, try it. Now:
- Close your application;
- Go to Control Panel / Regional and Language Options;
- On the "Regional Options" tab, click on the "Customize..." button;
- On the "Customize Regional Options" dialog box, change the "Decimal symbol" and the "Digit grouping symbol" in order to have them identical (for example, a comma in both cases);
- Confirm your new settings;
- Re-run your application: you'll get "
False" as a result.
This behavior is due to the ambiguity you created with these settings in the parsing algorithm that tries to convert your string to a number. Other functions such as
CDbl() will crash throwing a quite self-explaining exception in this situation, but not
IsNumeric(), which simply gives a wrong result...
Let's not discuss about the logic of setting the "Decimal symbol" equal to the "Digit grouping symbol". And let's not discuss about the fact that a system dialog box allows you this kind of a setting! Also, let's not talk about the users' stupidity (yes, I found a user so stupid!). Let's talk about a workaround, to make your code "safe" in the
A possible workaround
A good workaround consists in explicitly setting the current thread culture, and - with the culture - programmatically setting the "Decimal symbol" and the "Digit grouping symbol", as in:
Dim ci As New CultureInfo("it-IT")
Dim nfi As New NumberFormatInfo
nfi.CurrencyDecimalSeparator = ","
nfi.CurrencyGroupSeparator = "."
ci.NumberFormat = nfi
Thread.CurrentThread.CurrentCulture = ci
Of course, these settings you are "forcing" programmatically are limited to your application context and they won't influence (hopefully) anything else in the system.