代码之家  ›  专栏  ›  技术社区  ›  Jeppe Stig Nielsen

为什么美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲美洲。?

  •  20
  • Jeppe Stig Nielsen  · 技术社区  · 6 年前

    当我使用此代码时:

    var ri = new RegionInfo("us");
    var nativeName = ri.NativeName;   // ᏌᏊ ᎢᏳᎾᎵᏍᏔᏅ ᏍᎦᏚᎩ
    

    为什么 nativeName 然后是绳子 "ᏌᏊ ᎢᏳᎾᎵᏍᏔᏅ ᏍᎦᏚᎩ" (在 Cherokee )?

    如果我换成 new RegionInfo("US") (唯一不同的是资本 US ),我得到了 "United States" .

    了解 RegionInfo 是提供特定的区域性信息字符串,例如:

    new RegionInfo("en-US")
    new RegionInfo("chr-Cher-US")
    

    诸如此类,这是有效的。但为什么切罗基人比英语更受欢迎 只有 如果我用小写 us ?


    (见Windows 10(1803版“2018年4月更新”)。NET Framework 4.7.2。)


    更新:这是不一致的,即使在同一台机器上。例如,我多次尝试打开PowerShell,每次都是粘贴 [System.Globalization.RegionInfo]'US' 投入其中。似乎在很长一段时间内,PowerShell的所有实例都会给出相同的结果。但过了一会儿,PowerShell的实例给出了相反的结果。下面是其中两个窗口的屏幕截图,其中一个始终有一个 NativeName ,而另一个始终具有相反的一个。因此,必须进行一些非确定性的确定(套管无差异):

    PowerShell windows

    1 回复  |  直到 6 年前
        1
  •  8
  •   Gabriel Luci    6 年前

    首先要注意的是 constructor for RegionInfo 找到区域 通过寻找该地区使用的文化 .所以它在那个国家寻找一种语言,而不仅仅是这个国家。

    通读这些源代码,似乎大小写的差异是因为如果没有指定区域性,查找是如何进行的。

    例如,它首先尝试了几件事,但是 then it will try 看一眼 static list of regions .但因为它在使用 Dictionary.ContainsKey ,这是区分大小写的搜索。所以如果你指定 "US" ,它会找到它,但不会 "us" .

    后来 it searches through all the cultures (来自 CultureInfo.GetCultures(CultureTypes.SpecificCultures) )对于您提供的区域,但它不区分大小写。

    我无法确认,因为我无法单步执行该代码,但我的猜测是,因为它正在按顺序遍历列表,它将到达 chr-Cher-US 在它到达之前 en-US .

    为什么不一致?

    其中一条评论说,LinqPad即使使用大写字母也能找到切诺基。我不知道这是为什么。我能够复制它,但我也发现在VisualStudio中,当使用 “我们” 使用时使用切诺基 “我们” ,就像你描述的。但我确实发现,如果我在LinqPad中打开“使用实验性Roslyn程序集”,那么它会同时返回英语 “我们” “我们” .所以我不能确定,这可能与目标的确切运行时版本有关。

    影响一致性的一个因素是 缓存 :当它没有按文化+地区获得完全匹配时,它将做的第一件事 is check a cache of already-found cultures .它会降低缓存中所有密钥的大小写,因此此缓存不区分大小写。

    你可以测试一下。我们知道使用 “我们” 与。 “我们” 将产生不同的结果,但请在同一个程序中尝试:

    var nativeNameus = new RegionInfo("us").NativeName;
    var nativeNameUS = new RegionInfo("US").NativeName;
    

    然后交换它们并再次运行:

    var nativeNameUS = new RegionInfo("US").NativeName;
    var nativeNameus = new RegionInfo("us").NativeName;
    

    这两个结果总是相等的,因为第一个区域性被缓存并用于下一个区域性。

    代码之外可能有代码调用了相同的方法,并最终缓存了区域性值,从而改变了执行相同操作时得到的结果。

    结论

    尽管如此, the docs actually say :

    我们建议您使用文化名称,例如英语(美国)中的“en US”来访问NativeName属性。

    所以这有点没有实际意义:你要求的是一个地区,而不是一种语言。如果你需要一种特定的语言,可以要求使用这种语言,而不仅仅是一个地区。

    如果你想保证英语,那么:

    1. 按照微软的建议执行,并在区域中指定语言:“en-US”,或
    2. 使用 EnglishName DisplayName 属性(即使在 NativeName 是切罗基人)。