4

When I define the kelvin-sign (http://www.unicode-symbol.com/u/212A.html) like this:

var kelvinSign = "K";

And do a console writeline:

Console.WriteLine("{0} - {1}=>ToLower={2} - {3}=>ToLowerInvariant={4}",
                kelvinSign,
                kelvinSign.ToLower(), kelvinSign.ToLower() == "k",
                kelvinSign.ToLowerInvariant(), kelvinSign.ToLowerInvariant() == "k");

I get on one PC this output:

  • K - k=>ToLower=True - K=>ToLowerInvariant=False

And on another PC I get:

  • K - k=>ToLower=True - k=>ToLowerInvariant=True

Which indicates that the ToLowerInvariant() method does work differently?


Notes

  • on both systems the Thread.CurrentThread.CurrentCulture andThread.CurrentThread.UICurrentCulture is the same : "en-US"
  • both are running net5.0

Update
System that works has these settings:

  • OS = "Windows 10 PRO"
UseNls = False
CultureInfo.InvariantCulture =
CultureInfo.InvariantCulture.Name =
CultureInfo.InvariantCulture.CultureTypes = SpecificCultures, InstalledWin32Cultures
CultureInfo.InvariantCulture.DisplayName = Unknown language
CultureInfo.InvariantCulture.TwoLetterISOLanguageName = iv
CultureInfo.InvariantCulture.ThreeLetterISOLanguageName = ivl
CurrentCulture   = en-US
CurrentUICulture = en-US
K - k=>ToLower=True - k=>ToLowerInvariant=True

System that does not work has these settings:

  • OS = "Windows Server 2019" (actually this is a build-agent from Azure)
UseNls = True
CultureInfo.InvariantCulture = 
CultureInfo.InvariantCulture.Name = 
CultureInfo.InvariantCulture.CultureTypes = SpecificCultures, InstalledWin32Cultures
CultureInfo.InvariantCulture.DisplayName = Invariant Language (Invariant Country)
CultureInfo.InvariantCulture.TwoLetterISOLanguageName = iv
CultureInfo.InvariantCulture.ThreeLetterISOLanguageName = ivl
CurrentCulture   = en-US
CurrentUICulture = en-US
K - k=>ToLower=True - K=>ToLowerInvariant=False
Stef Heyenrath
  • 9,335
  • 12
  • 66
  • 121
  • 1
    Are you using different .NET versions on those two machines? – canton7 Aug 19 '21 at 13:33
  • 8
    .NET 5 [switched from NLS to ICU](https://learn.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu) for Unicode stuff, and it looks like they do things differently here. .NET 4.7.2: https://dotnetfiddle.net/cR09L7 vs .NET 5: https://dotnetfiddle.net/EdJ2aN – canton7 Aug 19 '21 at 13:37
  • Both are using net5.0 (I've updated my notes. ) – Stef Heyenrath Aug 19 '21 at 14:36
  • 1
    And you haven't used the [`System.Globalization.UseNls`](https://learn.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu#use-nls-instead-of-icu) option anywhere? Are you *sure* both actually target .NET 5 (as opposed to compiling for an earlier version, and then running on the .NET 5 runtime)? – canton7 Aug 19 '21 at 14:40
  • 1
    Analyze `CultureInfo.InvariantCulture` objects on both computers to spot if there are any differences – Dorin Baba Aug 19 '21 at 14:41
  • 2
    Run `Console.WriteLine(typeof(System.Globalization.CultureInfo).Assembly.GetType("System.Globalization.GlobalizationMode")?.GetProperty("UseNls", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) ?? "null");` on both of your platforms. What's the output on each? – canton7 Aug 19 '21 at 14:48
  • @canton7 The Nls setting is different. What is your proposed solution? – Stef Heyenrath Aug 19 '21 at 15:10
  • 2
    Aha, the Windows Server 2019 bit is probably key -- I suspect that doesn't have ICU available, so .NET is falling back to NLS there. If you care about this, you can either force your code to use NLS, or you can bundle a version of the ICU for it to use on all platforms. See [this doc](https://learn.microsoft.com/en-us/dotnet/standard/globalization-localization/globalization-icu) for details on both. – canton7 Aug 19 '21 at 15:23
  • 1
    ... BUT, the details of locales change over time. Some of this stuff changes between minor Windows 10 builds, or change based on what KBs are installed. You simply can't rely on it: show the results to the user, but don't write code which relies on any particular output. That said, having one of the "Invariant" methods change is weird, and probably won't happen that often. My preferred step would be to re-think your application so that you're not dependent on little details like this – canton7 Aug 19 '21 at 15:26

1 Answers1

1

The reason for this question was that I want to run the full test-set for XPath 2.0 in my unit-tests for XPath2.Net and have the same results on all systems.

But the XQTS_1_0_2 : caselessmatch04 had different results.

This is because my local development system is "Windows 10 Pro" and the build-agent from Azure has "Windows Server 2019", so my solution was to detect if Nls was used. For this I used the code example from canton7:

public static class GlobalizationUtils
{
    public static bool UseNls()
    {
        return (typeof(CultureInfo).Assembly.GetType("System.Globalization.GlobalizationMode")
            ?.GetProperty("UseNls", BindingFlags.Static | BindingFlags.NonPublic)
            ?.GetValue(null) as bool?) == true;
    }
}
Stef Heyenrath
  • 9,335
  • 12
  • 66
  • 121