Shaggydog
Shaggydog

Reputation: 3788

Culture invariant Decimal.TryParse()

I'm writing a custom string to decimal validator that needs to use Decimal.TryParse that ignores culture (i.e. doesn't care if the input contains "." or "," as decimal point separator). This is the suggested method:

public static bool TryParse(
    string s,
    NumberStyles style,
    IFormatProvider provider,
    out decimal result
)

I can't figure out what to use as the 3rd parameter. The examples I've seen look like this:

culture = CultureInfo.CreateSpecificCulture("en-GB");
Decimal.TryParse(value, style, culture, out number)

so they create a specific culture. CultureInfo does not have a "CreateInvariantCulture" method, and CultureInfo.InvariantCulture is not of the required type. What's the correct usage?

Upvotes: 54

Views: 105829

Answers (5)

Jan Bauer
Jan Bauer

Reputation: 51

This one works for me to parse decimals like 1.23:

decimal value;
string s = "1.23";
decimal.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out value);

// -> value = 1.23

it works independent from Windows locale, tested on a German Windows

Upvotes: 4

Soner Gönül
Soner Gönül

Reputation: 98740

I can't figure out what to use as the 3rd parameter.

Because all cultures NumberDecimalSeparator or NumberGroupSeparator etc.. are not the same.

Someones uses . as a NumberDecimalSeparator, someone uses , but there is no CultureInfo that uses both as a NumberDecimalSeparator.

CultureInfo implements IFormatProvider interface. That's why if you specify your CultureInfo, your value string try to be parsed on that cultures rules.

I'm writing a custom string to decimal validator that needs to use Decimal.TryParse that ignores culture

In such a case, you can use CultureInfo.Clone method to copy of which culture you want (or InvariantCulture) and you can set NumberDecimalSeparator and NumberGroupSeparator which string you want.

Upvotes: 3

Shaggydog
Shaggydog

Reputation: 3788

My bad guys. I tested the following code:

string DutchDecimal = "1,5";
string EnglishDecimal = "1.5";
decimal a;
decimal b;
Console.WriteLine(decimal.TryParse(DutchDecimal, out a));
Console.WriteLine(a);
Console.WriteLine(decimal.TryParse(EnglishDecimal, out b));
Console.WriteLine(b);
Console.Read();

And indeed it does not parse the Dutch decimal correctly, instead it returns 15 in that case, ignoring the unrecognized ,. As it turns out the default parser behavior is hardcoded to use whatever the current culture is of the currently running thread.

Upvotes: 6

mfas
mfas

Reputation: 71

I know this is a very old question, but it still pops up when searching for parsing with invariant culture.

I found the following in the documentation:

An invariant culture is culture-insensitive. Your application specifies the invariant culture by name using an empty string ("") or by its identifier.

So, using this knowledge, you can instantiate an invariant culture like this:

culture = new CultureInfo(string.Empty);

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 612804

In fact CultureInfo.InvariantCulture can be used here. The parameter expects IFormatProvider, an interface that CultureInfo implements. But InvariantCulture is invariant in the sense that it does not vary with the user's settings.

In fact, there is no culture that accepts either , or . as decimal separator – they are all one or the other. You'll have to find some other way to deal with data which can use either of these decimal separators.

Upvotes: 13

Related Questions