In 5.0.100-preview.7.20366.6 it seems as if the following code throws a FormatException. However, if I pass CultureInfo.InvariantCulture to the parse function it seems to work.
From what I can gather NegativeSign for my NumberFormat was changed from "-" to "−", I'm not sure whether this is due to some change in preview 7. According to my region settings the negative sign is not "−" but actually "-" whereas NumberFormat says that it's "−". Is this really correct?

Here's the code:
using System;
using System.Globalization;
namespace IntParseNegative
{
class Program
{
static void Main()
{
Console.WriteLine(CultureInfo.CurrentCulture);
try
{
int.Parse("-1");
}
catch (FormatException fe)
{
Console.WriteLine(fe.Message);
}
int.Parse("-1", CultureInfo.InvariantCulture);
}
}
}
The code is running 5.0.100-preview.7.20366.6 on Windows 10 Enterprise version 1909 on x64 architecture.
In 5.0.100-preview.3.20216.6 this code did not throw an exception.
Here's my CultureInfo.CurrentCulture:
{sv-SE}
Calendar: {System.Globalization.GregorianCalendar}
CompareInfo: {CompareInfo - sv-SE}
CultureTypes: SpecificCultures | InstalledWin32Cultures
DateTimeFormat: {System.Globalization.DateTimeFormatInfo}
DisplayName: "svenska (Sverige)"
EnglishName: "Swedish (Sweden)"
IetfLanguageTag: "sv-SE"
IsNeutralCulture: false
IsReadOnly: true
KeyboardLayoutId: 1053
LCID: 1053
Name: "sv-SE"
NativeName: "svenska (Sverige)"
NumberFormat: {System.Globalization.NumberFormatInfo}
OptionalCalendars: {System.Globalization.Calendar[1]}
Parent: {sv}
TextInfo: {TextInfo - sv-SE}
ThreeLetterISOLanguageName: "swe"
ThreeLetterWindowsLanguageName: "SVE"
TwoLetterISOLanguageName: "sv"
UseUserOverride: true
Here's CultureInfo.CurrentCulture.NumberFormat:
{System.Globalization.NumberFormatInfo}
CurrencyDecimalDigits: 2
CurrencyDecimalSeparator: ","
CurrencyGroupSeparator: "Â "
CurrencyGroupSizes: {int[1]}
CurrencyNegativePattern: 8
CurrencyPositivePattern: 3
CurrencySymbol: "kr"
DigitSubstitution: None
IsReadOnly: true
NaNSymbol: "¤¤¤"
NativeDigits: {string[10]}
NegativeInfinitySymbol: "−∞"
NegativeSign: "−"
NumberDecimalDigits: 3
NumberDecimalSeparator: ","
NumberGroupSeparator: "Â "
NumberGroupSizes: {int[1]}
NumberNegativePattern: 1
PerMilleSymbol: "‰"
PercentDecimalDigits: 3
PercentDecimalSeparator: ","
PercentGroupSeparator: "Â "
PercentGroupSizes: {int[1]}
PercentNegativePattern: 0
PercentPositivePattern: 0
PercentSymbol: "%"
PositiveInfinitySymbol: "∞"
PositiveSign: "+"
Here's CultureInfo.InvariantCulture.NumberFormat for comparison:
{System.Globalization.NumberFormatInfo}
CurrencyDecimalDigits: 2
CurrencyDecimalSeparator: "."
CurrencyGroupSeparator: ","
CurrencyGroupSizes: {int[1]}
CurrencyNegativePattern: 0
CurrencyPositivePattern: 0
CurrencySymbol: "¤"
DigitSubstitution: None
IsReadOnly: true
NaNSymbol: "NaN"
NativeDigits: {string[10]}
NegativeInfinitySymbol: "-Infinity"
NegativeSign: "-"
NumberDecimalDigits: 2
NumberDecimalSeparator: "."
NumberGroupSeparator: ","
NumberGroupSizes: {int[1]}
NumberNegativePattern: 1
PerMilleSymbol: "‰"
PercentDecimalDigits: 2
PercentDecimalSeparator: "."
PercentGroupSeparator: ","
PercentGroupSizes: {int[1]}
PercentNegativePattern: 0
PercentPositivePattern: 0
PercentSymbol: "%"
PositiveInfinitySymbol: "Infinity"
PositiveSign: "+"
Tagging subscribers to this area: @tarekgh, @safern, @krwq
See info in area-owners.md if you want to be subscribed.
In .NET 5, globalization is by default using ICU on Windows. Prior to .NET 5, it uses Win32 NLS.
Related #40258.
We can either switch from ICU to NLS on Windows, by exporting an environment variable: DOTNET_SYSTEM_GLOBALIZATION_USENLS=true or use culture.NumberFormat.NegativeSign for negative values with ICU.
@tarekgh, this keeps coming up. What would go wrong if we changed the code to consider - as a negative sign when parsing in addition to whatever the data says is the negative sign? Is that a terrible idea, or a feasible way to avoid this common problematic case?
@stephentoub
So you are suggesting that any culture specific format should fallback to invariant culture if it fails on parsing with the current culture? If not "any" why treat the negativ sign special?
Why not ditch current culture all together and only use the invariant one? /s
When I read this:
https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu
This note
Note
Even when using ICU, the CurrentCulture, CurrentUICulture, and CurrentRegion members still use Windows operating system APIs to honor user settings.
seems to be incorrect as OP mentioned the regional settings in the windows operating system differ from the setting that is accessable by code.
I'm not suggesting. I'm asking what the downsides would be. And specifically for - because it's close to impossible without them side by side to see the difference between − and - and this specific case has tripped up a lot of people.
this keeps coming up. What would go wrong if we changed the code to consider - as a negative sign when parsing in addition to whatever the data says is the negative sign? Is that a terrible idea, or a feasible way to avoid this common problematic case?
I hesitate to to do that because this can make us run into other problems when assuming '-' is the negative sign for all cultures. Some scenarios, is people can expect the parse failure when not having the right negative sign. another scenario is if anyone customize a numbers to use '-' a separator or something else. last, if we need to do that I would avoid to do it now that late in the cycle of this release.
If the CLDR intentionally set the negative sign of sv-SE to that character, then there is a good reason for that. If think this is wrong, can open issue for CLDR to fix that.
Our guidelines was always, to guarantee the parsing success, always use Invariant culture of formatting and parsing. This is why we are providing Invariant culture in the first place.
@vholmer We don't carry any globalization data. we'll just use the underlying OS globalization library. in .NET 5.0 we are using ICU library that ship with Windows too. you have the option to switch back to old 'NLS" behavior. you may consult the link https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu for doing that.
Why not ditch current culture all together and only use the invariant one? /s
That will be very wrong. users select specific culture in their profile to reflect that on the applications. You still have the option to set current user to Invariant if you want to do so.
According to my region settings the negative sign is not "−" but actually "-" whereas NumberFormat says that it's "−". Is this really correct?
This is something we need to look at to see why this is happening. we had a bug in earlier previews so this may be already fixed.
This is something we need to look at to see why this is happening. we had a bug in earlier previews so this may be already fixed.
This was fixed on Preview8. https://github.com/dotnet/runtime/issues/37121
@safern if you confirmed the user override is working, I think we can close this issue now.
@tarekgh @safern @stephentoub Thanks for the quick response everyone, looking forward to preview 8! 😄
(I'll leave the closing of this issue to you)
I'll try to repro this with Preview8/RC1 and will update.
I can confirm that this no longer reproes with Preview8 and RC1:
Preview7:
dotnet run
Input string was not in a correct format.
5.0.100-preview.8.20362.3:
dotnet run
-1
5.0.100-rc.1.20414.5:
dotnet run
-1
Test code:
static void Main(string[] args)
{
try
{
Console.WriteLine(int.Parse("-1"));
}
catch (FormatException fe)
{
Console.WriteLine(fe.Message);
}
int.Parse("-1", CultureInfo.InvariantCulture);
}


Closing the issue, thanks @vholmer
Most helpful comment
@tarekgh, this keeps coming up. What would go wrong if we changed the code to consider
-as a negative sign when parsing in addition to whatever the data says is the negative sign? Is that a terrible idea, or a feasible way to avoid this common problematic case?