C# parse string "0" to integer - c#

I have a new laptop at work and code that worked earlier in the week does not work today.
The code that worked before is, simplified:
while (dr.Read())
{
int i = int.Parse(dr.GetString(1))
}
Now it fails when the database value is 0. Sometimes, but not reliably, this will work instead:
while (dr.Read())
{
int i = Convert.ToInt32(dr["FieldName"]))
}
Am I missing something stupid?
Oddly enough, ReSharper is also having tons of weird errors with the same error message that I am getting with the above code: "input string was not in the correct format." (Starts before I even load a project.)
Any ideas? Anyone having any SP issues? I did try to make sure all my SPs were up-to-date when I got the machine.
EDIT: I understand how to use Try.Parse and error-handling. The code here is simplified. I am reading test cases from a database table. This column has only 0, 1, and 2 values. I have confirmed that. I broke this down putting the database field into a string variable s and then trying int.Parse(s). The code worked earlier this week and the database has not changed. The only thing that has changed is my environment.
To completely simplify the problem, this line of code throws an exception ("input string was not in the correct format"):
int.Parse("0");
EDIT: Thanks to everyone for helping me resolve this issue! The solution was forcing a reset of my language settings.

A possible explanation:
Basically, the problem was the
sPositiveSign value under
HKEY_CURRENT_USER\Control
Panel\International being set to 0,
which means the positive sign is '0'.
Thus, while parsing the "positive sign
0" is being cut off and then the rest
of the string ("") is parsed as a
number, which doesn't work of course.
This also explains why int.Parse("00")
wasn't a problem. Although you can't
set the positive sign to '0' through
the Control Panel, it's still possible
to do it through the registry, causing
problems. No idea how the computer of
the user in the post ended up with
this wrong setting...
Better yet, what is the output of this on your machine:
Console.WriteLine(System.Globalization.NumberFormatInfo.GetInstance(null).PositiveSign);
I'm willing to bet yours prints out a 0... when mine prints out a + sign.
I suggest checking your Control Panel > Regional and Language Options settings... if they appear normal, try changing them to something else than back to whatever language you're using (I'm assuming English).

I think it's generally not considered a good idea to call Convert.ToInt32 for the value reading out of database, what about the value is null, what about the value cannot be parsed. Do you have any exception handling code here.
Make sure the value is not null.
Check the value can be parsed before call Int32.Parse. Consider Int32.TryParse.
consider use a nullable type like int? in this case.
HTH.

Edit:
#Mike's response made me think that is extremely odd behavior and a simple google search yielded this result: int.Parse weird behavior
An empty string would also cause this issue.
You could check for dbnull before parsing, also it is good to validate parsed data.
You could use a default value and TryParse..
int i = -1;
if(!int.TryParse(dr["MyColumn"] as string, out i))
//Uh Oh!
Edit:
I posted this as a comment in #Chris' answer, but if the sql datatype is int then why not just use the GetInt32 method on the DataReater instead of retrieving it as a string and manual parsing it out?

Are you sure it's "0" and not "null"? What exception do you get?
EDIT:
Just out of curiosity, if it is really faulting on int.Parse("0"), can you try int.Parse("0", CultureInfo.InvariantCulture);?
Otherwise, post your query. Any joins?

you should check dr["FieldName"] != DBNull.Value and you should use TryParse if it passes the DBNull test...
if ( dr["FieldName"] != DBNull.Value )
{
int val = 0;
if ( int.TryParse( dr["FieldName"], out val ) )
{
i = val;
}
else
{
i = 0; // or some default value
}
}

I have seen this issue crop up with .NET Double class, parsing from string "0" as well.
Here's the really wacky part: you can get past the issue by using a different user account to run the program, and sometimes if you destroy and re-create the current user account on the machine, it will run fine.
I have yet to track this down, but you might get past it this way at least.

This is way out of left field, but check your localization settings. I had a number of "input string was not in a correct format" when I moved a web site to a Canadian server. The problem was in a DateTime.Parse method, and was fixed by setting the culture to "en-US".
Yes, your situation is different — but hey, you never know.

are you checking for null ?
if(!dr.IsNull("FieldName")){
int i = Convert.ToInt32(dr["FieldName"]))
}

Related

Setting CheckBox value to checked

Some context, I'm still rather new at c# but I've been updating c# code that someone else wrote that is incomplete. I've come across this code that seems to be giving me an error.
gblnEnableSSL = Convert.ToBoolean(Convert.ToInt32(Utils.GetSetting("Program", "Configuration", "SSL", "0")));
Utils.GetSetting("Program", "Configuration", "SSL", "0") returns a string "false" currently.
I've found that removing Convert.ToInt32() solves my problem. But, I was unconvinced that someone simply added Convert.ToInt32() that broke the code. I checked in the repo and was surprised to find that the previous code of the same line use to be:
gblnEnableSSL = Utils.GetSetting("Program", "Configuration", "SSL", "0").ToUpper() == "TRUE";
Which seemed to work as well. The checkbox checked value is set by using chkEnableSSL.Value = gblnEnableSSL;
My question is whether or not there is a difference between setting the value using a bool value or a string value. Also, is a difference between chkEnableSSL.value vs chkEnableSSL.Checked?
Edit: I'm not getting a compiler or run-time error with the previous code. It does not perform the code afterwards. For example, i have txtDataSource.Text = strDataSource; immediately after and it does not set the text unless i comment out gblnEnableSSL = ... or remove the Convert.ToInt32().
Edit:Convert.ToInt32() throws an exception but it did not break in VS because i didn't have "Common Language Runtime Exceptions" checked off.
It looks like GetSetting is returning a string. The first code example you gave is converting this string to an integer and then converting it to a boolean. The only way this would work is if the string values stored for that key are either 0 or 1. On your second code block it looks as if the values being used were not string values of 0 or 1 but actual string values of true or false. If the values stored in your config file are still in the format of true or false then this would be why your first line is breaking. You can't convert false or true strings to an int. It does look like someone just added something to break the code.
Also you don't mention what technology you are using. You could be using winforms, wpf, webforms, or MVC. I'm going to assume this is a web technology you are using because checbox.value is something I usually see in javascript. General consensus in setting checkbox values in javascript is by using the .prop() property which takes in a string as the property you want to change and a value as the second parameter. E.G.
$( "input" ).prop( "checked", true );
http://api.jquery.com/prop/
Moral of the story is remove the conversion to the int32 and use .prop() to set that checkbox :)

string.Compare("KHA","KTB",true) return incorrect result in C#

I am using C#, .NET 3.5. I have following code
string.Compare("KHA","KTB",true)
It returned value 1. This means KHA > KTB in alphabet order.
I expect it returns value -1.
Can anyone help me fix this?
Yes, all of you are right. It's because of the Culture. I add CultureInfo.InvariantCulture and it is solved.
Thanks all!
strig.Compare returns the relative position in the sort order. Since 'H' comes before 'T' that is why you are getting 1
Its should return -1, See the image
There must be something wrong going on with your compiler, it should return -1 and your understanding for the string.Compare is right.
You may try using CultureInfo.InvariantCulture:
int value = string.Compare("KHA", "KTB", true,CultureInfo.InvariantCulture);
The call string.Compare("KHA","KTB",true) should return -1 as expected. It does when I test it.
If you get any other result, you either are using other strings, or you have a default culture where 'T' is actually considered to come before 'H'.
For the latter case, you can specify a culture info in the call:
string.Compare("KHA", "KHB", true, CultureInfo.InvariantCulture)
If you are really getting 1 against string.Compare("KHA","KTB",true) then your system's current culture must be making an effect. Check the documentation of String.Compare. Also check the best practices of comparing a string here.

Parsing a decimal from a DataReader

I found a workaround for this error, but am now really curious as to why this would be happening, was wondering if anyone else has had this error.
My function is as follows:
public void Blog_GetRating(int blogID, ref decimal rating, ref int voteCount)
{
// Sql statements
// Sql commands
if (DataReader.Read())
{
// this line throws a 'Input string was not in a correct format.' error.
rating = decimal.Parse(DataReader["Rating"].ToString());
// this works absolutly fine?!
decimal _rating = 0;
decimal.TryParse(DataReader["Rating"].ToString(), out _rating);
rating = _rating;
}
}
Anyone ever seen that before?
What's even weirder is if i type this:
rating = decimal.Parse("4.0");
that works fine, the 4.0 is what is coming out from my DataReader.
As I said previous, the TryParse method works fine so it's not stopping me from carrying, but now I'm really interested to see if anyone has an answer for it.
Looking forward to some replies!
Sean
EDIT - SOLVED
The decimal.Parse method was working fine, the second time the function was running (was in a loop), a post hadn't been rated so a null value was being returned by the data reader. Wrapping COALESCE round my calculation in SQL solved the problem fine. Hence why, as you said, the tryparse method wasn't throwing an exception, just keeping the default of 0 to _rating.
That doesn't look weird to me at all.
Decimal.Parse() is supposed to throw an exception for bad formats. Decimal.TryParse() will not throw that exception, but instead just return false. The kicker is that you're not checking the return value from Decimal.TryParse(). I'll give you real good odds that Decimal.TryParse() returns false for every input that causes an exception with Decimal.Parse(), and true everywhere else. And when Decimal.TryParse() returns false, the output argument is always just "0".
The one possible caveat is localization. If Decimal.Parse() is complaining about a seemingly normal input, you might check if the number format (current culture) used on your server uses a comma rather than a decimal to separate the coefficient from the mantissa. But given your "4.0" test worked fine, I doubt this is the problem.
Finally, when doing this conversion from data reader you should consider the source column type of the data reader. If might already be a decimal. Why convert it to a string only to convert it back?
You are saying this:
// this works absolutly fine?!
decimal _rating = 0;
decimal.TryParse(DataReader["Rating"].ToString(), out _rating);
But you didn't actually check the return value of TryParse. I would guess that your TryParse is actually failing (returning false), since decimal.Parse and decimal.TryParse use the same "rules" for parsing, given the overloads you're using.
I suspect that neither is working as you think. Both are probably failing, but TryParse won't throw.
The sql decimal column won't parse to a string that can convert to a Decimal, so tryparse will return false. Try something like this:
if (Convert.IsDBNull(reader["DecimalColumn"]))
{
decimalData = 0m;
}
else
{
decimalData = reader.GetDecimal(reader.GetOrdinal("DecimalColumn"));
}
I am facing same problem today.
Try this:
rating = decimal.Parse("4,0");
It will give you same error.
The reason behind this is the culture. In the French culture, 4.0 is represented as 4,0, and hence it throws an Exception.
decimal.TryParse is culture invariant method and hence it works fine you.
Change your TryParse to this and try again:
if (!decimal.TryParse(DataReader["Rating"].ToString(), out _rating))
{
throw new Exception("Input string was not in a correct format");
}
I bet this does throw...

String Comparison set to boolean variable

I assume this should be fine
bool prefMatch = false;
// Is the frequency the same?
prefMatch = string.Compare(user.Frequency, pref.Action.ToString()) == 0;
so if user.Frequency is "3" and pref.Action.ToString() is "3" then it should set the prefMatch to true right? I'm getting false and I've definitely checked the 2 values in the watch tab in VS 2008 just to be sure they're the same
You can just use ==
prefMath = (user.Frequency == pref.Action.ToString());
Though string.Compare will also work. I suggest there is a problem elsewhere.
-- Edit
Also, just for completeness, there is no point assigning a variable to something, and then assigning it again directly after. It's slightly confusing to do so, so better to leave it unassigned, or assign it all in one spot. This way the compiler can help you if you have a case where it doesn't get assigned like you think. It is, obviously, acceptable to assign first if you wrap the second assignment in a try/catch though.
In situations like these, it's sometimes tempting to point the finger of blame at third-party code, as you've done here. Sometimes, this is justified - but not here. String.Compare is a central, extremely-well-tested piece of the .NET Framework. It's not failing. I guarantee it.
What I find helpful in these situations is to isolate the failure. Write a small, self-contained test case that attempts to demonstrate the problem. Write it with as few dependencies as possible. Make it a stand-alone console application, if possible. Post it here. If we can take it, compile and run it, and reproduce the problem, we can help you. I'd bet money, though, that in the course of creating this test case, you'll experience a head-slapping moment - "of course!" - and realize what the problem is.
Maybe the string(s) contain unprintable characters ?
To check, I'd do something like :
byte[] b1 = System.Text.Encoding.UTF8.GetBytes(user.Frequency);
byte[] b2 = System.Text.Encoding.UTF8.GetBytes(pref.Action.ToString());
then compare the contents of b1 and b2.

C# Why won't this substring work? Error: Input string was not in a correct format

The problem is with the convert of the txt box value, but why?
string strChar = strTest.Substring(0, Convert.ToInt16(txtBoxValue.Text));
Error is: Input string was not in a correct format.
Thanks all.
txtBoxValue.Text probably does not contain a valid int16.
A good way to avoid that error is to use .tryParse (.net 2.0 and up)
int subLength;
if(!int.TryParse(txtBoxValue.Text,out subLength)
subLength= 0;
string strChar = strTest.Substring(0, subLength);
This way, if txtBoxValue.Textdoes not contain a valid number then subLength will be set to 0;
One thing you may want to try is using TryParse
Int16 myInt16;
if(Int16.TryParse(myString, out myInt16)
{
string strChar = strTest.Substring(0, myInt16);
}
else
{
MessageBox.Show("Hey this isn't an Int16!");
}
A couple reasons the code could be faulty.
To really nail it down, put your short conversion on a new line, like this:
short val = Convert.ToInt16(txtBoxValue.Text);
string strChar = strTest.Substring(0, val);
Likely the value in txtBoxValue.Text is not a short (it might be too big, or have alpha characters in it). If it is valid and val gets assigned, then strTest might not have enough characters in it for substring to work, although this normally returns a different error. Also, the second parameter of substring might require an int (not sure, can't test right now) so you may need to actually convert to int32 instead of 16.
What is the value of txtBoxValue.Text during your tests?
ASP.NET offers several validation controls for checking user input. You should use something like a CompareValidator or RegularExpressionValiditor in your WebForm if you're expecting a specific type of input, eg, an Integer.

Categories

Resources