<decimal>.ToString("P3") returns Win7 和 Windows 10 上的不同结果

<decimal>.ToString("P3") returns differerent results on Win7 and Windows 10

我有两个盒子:一个 Win7 和另一个 Win10(还有一个 Windows Server 2012 盒子,它的行为与我的 Win10 盒子相同)。

所有盒子上都安装了 .NET 版本 4.5.2。

当我运行以下代码时:

Dim d As Decimal = 1.23
Console.WriteLine((d / 100D).ToString("P3"))

然后我在 Win7 上得到这个结果:

 1,230%

在 Win 10 和 Windows Server 2012 上我得到了这个结果:

 1,230 %

注意百分号前的 space。

谁能帮我看看为什么会这样?我仔细检查了.NET版本,它们都是4.5.2,所以这可能与操作系统有关吗?

非常感谢大家。

更新:

使用

Console.WriteLine((d / 100D).ToString("P3", CultureInfo.InvariantCulture))

我在所有机器上都得到了这个结果:

 1,230 %

但是当输出

Console.WriteLine(Thread.CurrentThread.CurrentCulture.Name)

在我得到的所有机器上

de-DE

我原以为文化一定会表现出不同的东西,因为会产生不同的结果,但由于一切都是去德的,我仍然不明白为什么不同操作系统的输出不同。

更新 2

...还有这个

Console.WriteLine((d / 100D).ToString("P3", CultureInfo.GetCultureInfo("de-DE")))

在 Win7 上的结果:

 1,230%

在 Win 10 和 Windows Server 2012 上我得到了这个结果:

 1,230 %

很奇怪,相同的文化,不同的输出...

"P" 格式说明符是 culture-sensitive,根据 Microsoft .NET Standard Numeric Format Strings documentation

Decimal.ToString(string, IFormatProvider) 重载中使用 CultureInfo.InvariantCulture 实现跨系统的一致 culture-agnostic 结果:

Dim d As Decimal = 1.23
Console.WriteLine((d / 100D).ToString("P3", CultureInfo.InvariantCulture))

更新

CultureInfo.InvariantCulture 告诉格式化方法忽略 thread-specific 区域性设置并使用随时间和机器保持一致的特殊通用区域性。

根据特定的文化,不同版本的 Windows:

One comment on different question 表明这是在 Windows 7 和 Windows 8 之间更改的。

不过,我觉得你的问题比较哲学。 Culture-sensitive 随着时间的推移,字符串看起来总是不同的。

一件事是软件部分 - 在 Windows 7 之前,百分比模式甚至不可用,因此您的字符串在 Vista 上可能已经看起来不同了。

另一件事是现实世界及其不断变化的条件。想象一下这种情况:明年您的国家可能会出台新的语法规则,其中将指定要使用的不同格式。 Microsoft 将发布更新,调整默认设置以匹配这些规则。但是,在给定的时间点,有些用户不会安装更新,因此会得到不同的字符串。有些用户可能多年不更新。

您的程序重新实现 culture-dependent 细节是否有意义,或者这应该是操作系统的责任?拥有自己的文化规则将使您的程序看起来很奇怪,因为该计算机上的大多数其他程序将具有与 OS 一致的文化规则(除非它们的作者也决定重新实现文化)。当然,还有一个问题是微软是否应该在 Windows 版本之间的百分比格式中添加 space 。但恐怕那艘船几年前就已经航行了,我们只能忍受它。同样,它会影响 culture-sensitive 字符串,这些字符串无论如何都容易随时间发生变化。

如果你真的必须这样做,我想你最好的选择是为每个线程克隆文化并设置 CultureInfo.NumberFormat.PercentPositivePattern = 1;