views:

34

answers:

2

I have some issues with number <-> string conversion i cannot sort out.

We have written a serialization framework which uses several xml serialization techniques. But i have seen some inconsistent number conversions in the generated output:

using:

var c = TypeDescriptor.GetConverter(double);
var s = c.ConvertToString(value);

and

var c = TypeDescriptor.GetConverter(double);
return c.ConvertFromString(value.Value);

I get strings with comma separator like 3,33 and conversion back to double works, but will conversion back to double also work in another country which uses dot as separator? (I am in germany, we use comma, but besides that, i want the dot seperator)

Then in another part of the code i convert the doubles in some structs directly by adding it to a XElement:

data.Add(new XElement("x", vector.x));

The XElement constructor converts the double to a string with dot like "3.33".

It gets really strange, when i want to convert this string back to a double:

Double.TryParse(item.Value, out value.x);

and

value.x = Convert.ToDouble(item.Value);

both ignore the dot and i have a double value of 333!?

so i tried it there also with the TypeConverter code, but it gives me an exception, that "3.33" is no valid string for the double converter...

Now what i really need is a number <-> string conversion which always uses dot separator and also parses it righ, regardless the culture/localization settings...

i am lost.. which should i use? i even tried things like:

    NumberFormatInfo provider = new NumberFormatInfo();

    provider.NumberDecimalSeparator = ".";
    provider.NumberGroupSeparator = " ";
    provider.NumberGroupSizes = new int[] { 3 };

    foreach (var item in CultureInfo.GetCultures(CultureTypes.AllCultures))
    {
        item.NumberFormat = provider;
    }

but it didn't help.. thanks for any hint..

+2  A: 

You want the invariant culture: CultureInfo.InvariantCulture.

HTH

Kent Boogaart
+3  A: 

An example on how to "fix" this issue. Assuming this is the original:

double ParseString(string s)
{
     return double.Parse(s);
}

this is one type of fix

double ParseString(string s)
{
     return double.Parse(s, CultureInfo.InvariantCulture);
}

here is another you can use if you have a large number of Parses()

double ParseString(string s)
{
     // Save off previous culture and switch to invariant for serialization.
     CultureInfo previousCulture = Thread.CurrentThread.CurrentCulture;
     Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

     double result = double.Parse(s, CultureInfo.InvariantCulture);

     Thread.CurrentThread.CurrentCulture = previousCulture;

     return result;
}
Donblas
I'd be wary of replacing `Thread.CurrentCulture` as per the last example. Clearly, this isn't thread-safe and if another thread relies on `CurrentCulture` being the user's culture, then *bang*!
Kent Boogaart
Doesn't Thread.CurrentCulture only switch it for the current thread?
Donblas
hopefully, i did it like this now.. can someone clear this up?
thalm