51

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?

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Shaggydog
  • 3,456
  • 7
  • 33
  • 50

4 Answers4

13

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
6

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.

Abel
  • 56,041
  • 24
  • 146
  • 247
Shaggydog
  • 3,456
  • 7
  • 33
  • 50
  • 1
    From the [Microsoft Documentation](https://msdn.microsoft.com/en-us/library/9zbda557(v=vs.110).aspx) it looks like .NET turns to your local system settings if you do not specify a culture: `Parameter s is parsed using the formatting information in a NumberFormatInfo object initialized for the current system culture.` – Rune Vejen Petersen Aug 17 '16 at 14:26
  • 4
    Parsing 1,5 to 15 isn't really correct, is it? If ',' is a thousands-separator it shouldn't be allowed at the 10-position. I think parsing 1,5 using culture invariant parsing should fail. – avl_sweden Jun 26 '17 at 14:10
  • 2
    @avl_sweden it is not correct to assume comma is a thousands-separator when it's not a decimal separator. For example, where Sweden would write "1,234,567.89", India would write "12,34,567.89" and China would write "123,4567.89". Number-formatting is not so straight-forward. My guess is, when the comma is not a decimal separator, it is just ignored completely by the parser. – Peter Sep 27 '18 at 14:35
  • @Peter "1,234,567.89" is not correct in swedish. We use spaces as thousands-separator and comma as decimal-separator. – Mattias Örtenblad May 08 '19 at 13:29
  • 1
    Actually it depends on your current locale, and in your case it seems is sees the point as the decimal separator. I have my locale set to dutch and it actually parses '1.5' to '15'. So if you rely now on it '1,5' to actually convert to '15' then you might be in for a suprise if your application is run on another computer with different locale settings. – SuperDre May 19 '20 at 17:19
3

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.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
0

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);
mfas
  • 71
  • 1
  • 6