.Net 5.0 Preview 7, fails on Int.Parse("-1") with
Message:
System.FormatException : Input string was not in a correct format.
Stack Trace:
Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
Number.ParseInt32(ReadOnlySpan`1 value, NumberStyles styles, NumberFormatInfo info)
Int32.Parse(String s)
NetCore50prev7_Tests.NegativeIntegerFailsParse() line 15
public class NetCore50prev7_Tests
{
[Fact]
public void NegativeIntegerFailsParse()
{
int.Parse("-1");
}
}
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
@eriksimonic what is the current culture?
Console.WriteLine(CultureInfo.CurrentCulture);
and OS?
@EgorBo
Windows 10 2004, build 19041.388
Culture is sl-SI
If I change the culture to CultureInfo.InvariantCulture, the parse works.
Console.WriteLine(string.Join(", ", Encoding.Unicode.GetBytes("-"))); // en-US negative sign
Console.WriteLine(string.Join(", ", Encoding.Unicode.GetBytes("−"))); // sl-SI negative sign
{45, 0}
{18, 34}
sl-SI locale uses a slightly different negative sign 🙂
You can obtain it via new CultureInfo("sl-SI").NumberFormat.NegativeSign
Tagging subscribers to this area: @tarekgh, @safern, @krwq
See info in area-owners.md if you want to be subscribed.
@EgorBo , this works correctly in .net core 5.0 or any other, It is this a "feature"
hm... indeed, 🤔
Console.WriteLine(int.Parse("-1", new CultureInfo("sl-SI")));
works for net4x and netcoreapp3.1 (windows)
but doesn't work for net5 (windows and nix) and netcoreapp3.1 (nix, ICU)
Hasn't net5 moved to ICU on windows also?
Yes. net5 switched to ICU library on Windows. Some cultures (e.g. en-US) work with multiple minus signs U+002D and U+221 with ICU. Apparently not the case with sl-SI. Interestingly, there was a related bug for Slovenian minus sign (U+2013), which was fixed last year in release 31: https://unicode-org.atlassian.net/browse/CLDR-10050.
@eriksimonic as a workaround you can define an env. variable DOTNET_SYSTEM_GLOBALIZATION_USENLS=true to rely on NLS instead of ICU on Windows.
Yes this is by design as we switched to ICU. sl-SI is not using - as the negative sign. If you are parsing with such culture you have to provide the correct negative sign. As mentioned earlier in the discussion, to workaround it, either use different culture e.g. Invariant, or enable NLS by the config switch System.Globalization.UseNls https://docs.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu.
You could also write a method that tries both
int ParseInt(string value)
{
if (int.TryParse(value, out int result))
{
return result;
}
return int.Parse(value, CultureInfo.InvariantCulture);
}
@benaadams , hard to do when third party library uses the method.
@tarekgh why such a braking change?
At least is <InvariantGlobalization>true</InvariantGlobalization> fisible option.
Thanks.
@eriksimonic - Outside the move to ICU, this sort of thing is always possible; you can construct/use custom cultures on windows that would have the same effect.
It might be handy to know what sort of third-party library you're using here; for instance, if you're doing data serialization/processing, you should likely be in the invariant culture anyways. Although I'd probably raise a bug with them if you can't override the culture/formatting options.
@eriksimonic, the answer of @Clockwork-Muse is correct. .NET 5.0 is by default using ICU and NLS. you have the option to switch back to NLS. but I wouldn't recommend that because NLS data can change too especially Windows working hard to converge with CLDR data which is shipped with ICU. As @Clockwork-Muse mentioned, if you want to guarantee the parsing, you should format and parse using Invariant culture.
Most helpful comment
@eriksimonic as a workaround you can define an env. variable
DOTNET_SYSTEM_GLOBALIZATION_USENLS=trueto rely on NLS instead of ICU on Windows.