I have some legacy code running on .NET Framework 4.8 which sorts some product codes and puts the result in a single database column. This has been running for years accumulating data I can't easily modify. I need it to work the same on .NET 7.
The code is simple:
Code
new[] { "123-CAT", "123CAT" }.OrderBy(x => x).ToArray();
.NET Framework
[ "123CAT", "123-CAT" ]
.NET 7
[ "123-CAT", "123CAT" ]
I need the .NET 7 code to match the .NET Framework result.
So I played around with different cultures thinking it would be simple. To my surprise I could not find any StringComparer
culture in .NET 7 that would give the result ["123CAT", "123-CAT"]
.
These are all the versions I tried. The values marked with ***
are the result I want.
// .NET Framework: 123CAT, 123-CAT ***
// .NET 7 : 123-CAT, 123CAT
var list_default = new[] { "123-CAT", "123CAT" }.OrderBy(x => x).ToArray();
// .NET Framework: 123CAT, 123-CAT ***
// .NET 7 : 123-CAT, 123CAT
var list_currentCulture = new[] { "123-CAT", "123CAT" }.OrderBy(x => x, StringComparer.CurrentCulture).ToArray();
// .NET Framework: 123CAT, 123-CAT ***
// .NET 7 : 123-CAT, 123CAT
var list_invariant = new[] { "123-CAT", "123CAT" }.OrderBy(x => x, StringComparer.InvariantCulture).ToArray();
// .NET Framework: 123-CAT, 123CAT
// .NET 7 : 123-CAT, 123CAT
var list_ordinal = new[] { "123-CAT", "123CAT" }.OrderBy(x => x, StringComparer.Ordinal).ToArray();
Based on ASCII table I would expect and probably want the 123-CAT
to come first (since the - is an ASCII 45 character) and .NET 7 is doing exactly that. But I need it to match the .NET Framework behavior.
I can get .NET Framework to match .NET 7 (using StringComparer.Ordinal
) but not the other way around!
CodePudding user response:
In .NET 5 on Windows was breaking change which switched globalization to ICU from NLS. To revert to NLS on Windows you can add next xml switch to .cpproj:
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>