C# 中开尔文符号 (K) 的 ToLowerInvariant 具有不同的结果

ToLowerInvariant from a Kelvin Sign (K) in C# has different results

提问人:Stef Heyenrath 提问时间:8/19/2021 最后编辑:Stef Heyenrath 更新时间:8/20/2021 访问量:181

问:

当我这样定义开尔文符号 (http://www.unicode-symbol.com/u/212A.html) 时:

var kelvinSign = "K";

并执行控制台写入行:

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

我在一台 PC 上得到这个输出:

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

在另一台 PC 上,我得到:

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

这表明 ToLowerInvariant() 方法的工作方式确实不同?


笔记

  • 在两个系统上,和是相同的:Thread.CurrentThread.CurrentCultureThread.CurrentThread.UICurrentCulture"en-US"
  • 两者都在运行 Net5.0

正常工作的更新
系统具有以下设置:

  • 操作系统 =“Windows 10 专业版”
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

不工作的系统具有以下设置:

  • OS = “Windows Server 2019”(实际上这是来自 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
C# 小写 区域性 invariantculture

评论

1赞 canton7 8/19/2021
是否在这两台计算机上使用不同的 .NET 版本?
8赞 canton7 8/19/2021
.NET 5 从 NLS 切换到 ICU 用于 Unicode 内容,看起来他们在这里做事的方式不同。.NET 4.7.2:dotnetfiddle.net/cR09L7 与 .NET 5:dotnetfiddle.net/EdJ2aN
1赞 canton7 8/19/2021
您还没有在任何地方使用过 System.Globalization.UseNls 选项?是否确定两者都实际面向 .NET 5(而不是针对早期版本进行编译,然后在 .NET 5 运行时上运行)?
2赞 canton7 8/19/2021
在您的两个平台上运行。每个的输出是什么?Console.WriteLine(typeof(System.Globalization.CultureInfo).Assembly.GetType("System.Globalization.GlobalizationMode")?.GetProperty("UseNls", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) ?? "null");
2赞 canton7 8/19/2021
啊哈,Windows Server 2019 位可能是关键——我怀疑它没有可用的 ICU,所以 .NET 正在回退到 NLS。如果您关心这一点,您可以强制代码使用 NLS,也可以捆绑 ICU 的一个版本供其在所有平台上使用。有关两者的详细信息,请参阅此文档

答:

1赞 Stef Heyenrath 8/20/2021 #1

这个问题的原因是我想在 XPath2.Net 单元测试中运行 XPath 2.0 的完整测试集,并在所有系统上获得相同的结果。

但是XQTS_1_0_2:caselessmatch04 有不同的结果。

这是因为我的本地开发系统是“Windows 10 Pro”,而 Azure 的 build-agent 是“Windows Server 2019”,所以我的解决方案是检测是否使用了 NLS。为此,我使用了 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;
    }
}