Convert.ToInt32("0") throws an exception, some systems

M

Michael Petrotta

I have an odd problem affecting some of my customer's systems. I've
reduced it down to a simple, but bedeviling issue: Int32.Parse is
failing to convert the string "0", on some systems.

On those systems, the Framework throws a FormatException ("Input string
was not in a correct format."). Convert.ToInt32 does the same thing.
Every other single-digit string ("1", "2",..."9") works fine, as does
any two-digit string with a leading 0 ("03", "04", etc). And yes, I've
checked that I'm using a zero, and not the letter "O".

Here's how I reproduced it:

using System;
namespace ParseTest
{
class Program
{
static void Main()
{
int i = Convert.ToInt32("0"); // throws a FormatException on some
systems
Console.WriteLine("parsed: " + i);
Console.Read();
}
}
}

I can work around this by calling Convert.ToInt32 with a base argument:
Convert.ToInt32("0", 10). When I reflect on that method, I see that
Convert.ToInt32(string) follows a completely different code path than
does Convert.ToInt32(string, int). The one-arg overload calls directly
into Int32.Parse, and the two-arg overload calls
ParseNumbers.StringToInt. The one-arg overload does an explicit parse
test (Number.ParseNumber) that fails, and the two-arg overload calls
into an internal call that I can't follow.

Specifying the numeric base will fix some of our problems, but not all;
some of these parse errors are generated by the same calls deep inside
third-party components.

This only happens on .NET 2.0. 1.1 parses this string on all systems
without trouble.

This sample code will probably work for you; it's only failing on some
systems. Guessing that this might be a localization issue, I checked
one machine's "Regional and Language Options" control panel. Every
standard and advanced setting looked fine, and the format was set to
"English (United States)". .Net reports the current culture set to
en-US.

Here's a funny bit - when I switched the control panel's format from US
to something else, and back to US, the problem resolved itself. No
more problems parsing zero. No amount of further fiddling with the
control panel would bring the problem back. I took a before-and-after
snapshot of what I think was the relevant section of the registry
(HKEY_CURRENT_USER\Control Panel\International). No changes.

So I have a way to resolve this on clients experiencing this error -
twiddle their culture setting. It seems like some culture bits got
messed up, which I would expect to see on an isolated machine but not
on the number I've seen here. Has anyone else experienced this, or
have any idea why it's happening? Seems like a bug to me - any reason
not to file this?

Thanks for any help,

Michael
 
A

Alvin Bruney [MVP]

I would go ahead and file it, the most that can be said is after filing is
that it isn't a bug. No harm done right?
 
K

k3nn

i used this simple function to overcome the bug on some systems. This function can only correctly convert integer strings (i.e., "019", "20", etc), since this is just what I needed.

public Int32 ToInt32(string theValue)
{
Int32 retVal = 0;
for (int n = theValue.Length, m = 0; n > 0; n--, m++)
{
retVal += (Int32 )Math.Pow(10, m) * ((Int32 )Convert.ChangeType(theValue[n - 1], TypeCode.Int32) - 48);
}
return retVal;


__
Newsgroups brought to you courtesy of www.dotnetjohn.com
 
M

Michael Petrotta

i used this simple function to overcome the bug on some systems. This function can only correctly convert integer strings (i.e., "019", "20", etc), since this is just what I needed.

public Int32 ToInt32(string theValue)
{
Int32 retVal = 0;
for (int n = theValue.Length, m = 0; n > 0; n--, m++)
{
retVal += (Int32 )Math.Pow(10, m) * ((Int32 )Convert.ChangeType(theValue[n - 1], TypeCode.Int32) - 48);
}
return retVal;
}

Here's the call I used to work around this issue, on my systems:
Convert.ToInt32(val, 10) // second arg is numeric base

I didn't walk through your method, but I can see several problems, even
when the method is called with integer values.

Console.WriteLine("6.0 : " + ToInt32("6.0"));
Console.WriteLine("-2 : " + ToInt32("-2"));
Console.WriteLine("123456789012 : " + ToInt32("123456789012"));

prints

6.0 : 580
-2 : -28
123456789012 : 1309305364

I mention this because there's a temptation, particularly by later
maintainers of your code, to use methods with such a broad name more
broadly than originally intended.

Michael
 
J

jalbao

i used this simple function to overcome the bug on some systems. This function can only correctly convert integer strings (i.e., "019", "20", etc), since this is just what I needed.
public Int32 ToInt32(string theValue)
{
Int32 retVal = 0;
for (int n = theValue.Length, m = 0; n > 0; n--, m++)
{
retVal += (Int32 )Math.Pow(10, m) * ((Int32 )Convert.ChangeType(theValue[n - 1], TypeCode.Int32) - 48);
}
return retVal;
}

Here's the call I used to work around this issue, on my systems:
Convert.ToInt32(val, 10) // second arg is numeric base

I didn't walk through your method, but I can see several problems, even
when the method is called with integer values.

Console.WriteLine("6.0 : " + ToInt32("6.0"));
Console.WriteLine("-2 : " + ToInt32("-2"));
Console.WriteLine("123456789012 : " + ToInt32("123456789012"));

prints

6.0 : 580
-2 : -28
123456789012 : 1309305364

I mention this because there's a temptation, particularly by later
maintainers of your code, to use methods with such a broad name more
broadly than originally intended.

Michael

I have experienced this same issue on two WinXP SP2 Framework 2.0
machines .

The work-around of changing the Locale settings that Michael figured
out solved the problem - Thanks Michael!

After reading the bug post that Michael made on the feedback forums, I
thought it may be useful to share that in the two systems that I was
working with, the International reg keys were not different after I
made the Locale changes. For the record, here is what the reg key
values were before AND after the Locale changes:

[HKEY_CURRENT_USER\Control Panel\International]
iCountry="1"
iCurrDigits="2"
iCurrency="0"
iDate="0"
iDigits="2"
iLZero="1"
iMeasure="1"
iNegCurr="0"
iTime="0"
iTLZero="0"
Locale="00000409"
s1159="AM"
s2359="PM"
sCountry="United States"
sCurrency="$"
sDate="/"
sDecimal="."
sLanguage="ENU"
sList=","
sLongDate="dddd, MMMM dd, yyyy"
sShortDate="M/d/yyyy"
sThousand=","
sTime=":"
sTimeFormat="h:mm:ss tt"
iTimePrefix="0"
sMonDecimalSep="."
sMonThousandSep=","
iNegNumber="1"
sNativeDigits="0123456789"
NumShape="1"
iCalendarType="1"
iFirstDayOfWeek="6"
iFirstWeekOfYear="0"
sGrouping="3;0"
sMonGrouping="3;0"
sPositiveSign=""
sNegativeSign="-"

[HKEY_CURRENT_USER\Control Panel\International\Geo]
Nation="244"

Thanks again, Michael, for the work-around.

Jed
 
J

jalbao

i used this simple function to overcome the bug on some systems. This function can only correctly convert integer strings (i.e., "019", "20", etc), since this is just what I needed.
public Int32 ToInt32(string theValue)
{
Int32 retVal = 0;
for (int n = theValue.Length, m = 0; n > 0; n--, m++)
{
retVal += (Int32 )Math.Pow(10, m) * ((Int32 )Convert.ChangeType(theValue[n - 1], TypeCode.Int32) - 48);
}
return retVal;
}
Here's the call I used to work around this issue, on my systems:
Convert.ToInt32(val, 10) // second arg is numeric base
I didn't walk through your method, but I can see several problems, even
when the method is called with integer values.
Console.WriteLine("6.0 : " + ToInt32("6.0"));
Console.WriteLine("-2 : " + ToInt32("-2"));
Console.WriteLine("123456789012 : " + ToInt32("123456789012"));

6.0 : 580
-2 : -28
123456789012 : 1309305364
I mention this because there's a temptation, particularly by later
maintainers of your code, to use methods with such a broad name more
broadly than originally intended.

I have experienced this same issue on two WinXP SP2 Framework 2.0
machines .

The work-around of changing the Locale settings that Michael figured
out solved the problem - Thanks Michael!

After reading the bug post that Michael made on the feedback forums, I
thought it may be useful to share that in the two systems that I was
working with, the International reg keys were not different after I
made the Locale changes. For the record, here is what the reg key
values were before AND after the Locale changes:

[HKEY_CURRENT_USER\Control Panel\International]
iCountry="1"
iCurrDigits="2"
iCurrency="0"
iDate="0"
iDigits="2"
iLZero="1"
iMeasure="1"
iNegCurr="0"
iTime="0"
iTLZero="0"
Locale="00000409"
s1159="AM"
s2359="PM"
sCountry="United States"
sCurrency="$"
sDate="/"
sDecimal="."
sLanguage="ENU"
sList=","
sLongDate="dddd, MMMM dd, yyyy"
sShortDate="M/d/yyyy"
sThousand=","
sTime=":"
sTimeFormat="h:mm:ss tt"
iTimePrefix="0"
sMonDecimalSep="."
sMonThousandSep=","
iNegNumber="1"
sNativeDigits="0123456789"
NumShape="1"
iCalendarType="1"
iFirstDayOfWeek="6"
iFirstWeekOfYear="0"
sGrouping="3;0"
sMonGrouping="3;0"
sPositiveSign=""
sNegativeSign="-"

[HKEY_CURRENT_USER\Control Panel\International\Geo]
Nation="244"

Thanks again, Michael, for the work-around.

Jed

I forgot to mention in my last post -

On both machines that I was working with had Microsoft Office 2003 Pro
installed. All the Office apps were 2003 EXCEPT Microsoft Access - On
both machines, Access 97 was being used in place of Access 2003.

I have no idea if there is a connection with this type of Office setup
and the strange Convert.ToInt32("0") error, but I thought I'd post it
here for the record.

By the way, int.Parse("0") throws the exception too.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top