6

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!

5
  • Try adding <ItemGroup> <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" /> </ItemGroup> to csproj Commented Feb 4, 2023 at 9:56
  • 1
    See .NET globalization and ICU Commented Feb 4, 2023 at 9:57
  • @shingo. US-en on Windows 11. And the code is normally running on Windows Server 2018. Commented Feb 4, 2023 at 10:03
  • @GuruStron That did it :-) I found all the culture stuff but didn't think to search for Globalization. If you want to add that as an answer I can accept it. And now I can sleep better :-) And hope this doesn't have any other impact! Commented Feb 4, 2023 at 10:07
  • 1
    Although ironically, I'm considering switching to a Mac for some development so it may end up being easier to switch the legacy code to use Ordinal and just batch update everything. But this will work great for now. Commented Feb 4, 2023 at 10:13

1 Answer 1

4

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>

Read more:

Sign up to request clarification or add additional context in comments.

3 Comments

Hidden in that page is this very useful article about string comparison changes: learn.microsoft.com/en-us/dotnet/standard/base-types/…
I decided in the end to bite the bullet and change both to OrdinalIgnoreCase and go back and clean the database. I only have 12,104 unique combinations over 1.1 million rows. So here goes... and thanks again for your quick reply.
@SergeySlepov I would argue that this was a quite necessary measure cause otherwise you would have different behaviour on different platforms.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.