CultureInfo.InvariantCulture 是啥意思?

Posted

技术标签:

【中文标题】CultureInfo.InvariantCulture 是啥意思?【英文标题】:What does CultureInfo.InvariantCulture mean?CultureInfo.InvariantCulture 是什么意思? 【发布时间】:2012-03-18 16:54:27 【问题描述】:

我有一串这样的文字:

var foo = "FooBar";

我想声明第二个字符串 bar 并使其等于我的第一个 foo 的第一个和第四个字符,所以我这样做:

var bar = foo[0].ToString() + foo[3].ToString();

这按预期工作,但ReSharper 建议我将Culture.InvariantCulture 放在我的括号内,所以这条线的结尾是这样的:

var bar = foo[0].ToString(CultureInfo.InvariantCulture)
        + foo[3].ToString(CultureInfo.InvariantCulture);

这是什么意思,它会影响我的程序的运行方式吗?

【问题讨论】:

查看这个 SO 问题:***.com/questions/8492449/… 对于那些寻找 5 秒答案的人:CultureInfo.InvariantCulture 的意思是“我不在乎,我不希望首先涉及文化。现在让我使用愚蠢的东西。” @Andrew 你能重写 MS 的所有文档吗? @Yatrix 是的,当然。我喜欢!谁付钱? 【参考方案1】:

并非所有文化都对日期和十进制/货币值使用相同的格式。

当您将存储为字符串的输入值(读取)转换为DateTimefloatdoubledecimal 时,这对您很重要。如果您尝试将上述数据类型格式化为字符串 (write) 以进行显示或存储,这也很重要。

如果您提前知道日期和十进制/货币值的特定文化,您可以使用特定的CultureInfo 属性(即CultureInfo("en-GB"))。例如,如果您期望用户输入。

CultureInfo.InvariantCulture 属性用于格式化或解析应该可由独立于用户本地设置的软件解析的字符串。

默认值为CultureInfo.InstalledUICulture,因此默认 CultureInfo 取决于执行操作系统的设置。这就是为什么您应该始终确保文化信息符合您的意图(请参阅Martin's answer 以获得良好的指导)。

CultureInfo.InvariantCulture Example CultureInfo.InvariantCulture on *** CultureInfo.InvariantCulture MSDN Article Predefined CultureInfo Names

【讨论】:

"en-US" 不过,我认为这实际上可能取决于您的系统设置。 默认值不是en-US。这是当地的文化。当您想要独立于本地系统的文化中性格式时,使用InvariantCulture。例如,在处理基于文本的文件格式时。 添加到@CodesInChaos 评论:默认值为 CultureInfo("en-US") 的说法是完全错误的。此外,当您提前不确定日期和十进制/货币值将采用哪种文化格式时,使用声明 CultureInfo.InvariantCulture 属性。 令人困惑。使用当前的、不变的或特定的文化应该是一个有意识的决定,如果你弄错了,你可能会疏远你的(非美国)用户。如果您“不确定”,则不应使用不变的文化。您需要提前确定。 -1 由于其他 cmets 中提到的问题。 Martin 的回答更有帮助,因为它告诉您何时使用和不使用每种文化。 "如果您只使用美式英语工作,则无需担心。":不正确,您可能只使用美式英语工作,但软件可能运行在" en-GB”或“de-DE”服务器,那么它会有所作为,而且它可以采用客户端的文化(如果您在 web.config 文件中这么说),那可能不是“en-US”要么……【参考方案2】:

当数字、日期和时间被格式化为字符串或从字符串中解析时,文化被用来确定它是如何完成的。例如。在占主导地位的 en-US 文化中,您有以下字符串表示形式:

1,000,000.00 - 100 万,带有两位数的小数 1/29/2013 - 发布日期

在我的文化 (da-DK) 中,这些值具有以下字符串表示形式:

1.000.000,00 - 100 万,带两位小数 29-01-2013 - 发布日期

在 Windows 操作系统中,用户甚至可以自定义数字和日期/时间的格式,还可以选择不同于其操作系统文化的其他文化。使用的格式是用户的选择,应该是这样的。

因此,当您使用ToStringString.Format 格式化要显示给用户的值或使用DateTime.ParseDecimal.Parse 从字符串解析时,默认使用CultureInfo.CurrentCulture。这允许用户控制格式。

然而,很多字符串格式化和解析实际上并不是在应用程序和用户之间交换字符串,而是在应用程序和某些数据格式(例如 XML 或 CSV 文件)之间交换。在这种情况下,您不想使用CultureInfo.CurrentCulture,因为如果格式化和解析是使用不同的文化完成的,它可能会中断。在这种情况下,您想使用CultureInfo.InvariantCulture(它基于en-US 文化)。这确保了这些值可以毫无问题地往返。

ReSharper 向您发出警告的原因是一些应用程序编写者没有意识到这种区别,这可能会导致意想不到的结果,但他们从未发现这一点,因为他们的 CultureInfo.CurrentCultureen-US,其行为与 CultureInfo.InvariantCulture 相同.但是,一旦应用程序在另一种文化中使用,其中有可能使用一种文化进行格式化而另一种文化用于解析,应用程序可能会中断。

总结一下:

如果您正在格式化或解析用户字符串,请使用 CultureInfo.CurrentCulture(默认值)。 如果您正在格式化或解析应该可由软件解析的字符串,请使用 CultureInfo.InvariantCulture。 很少使用特定的国家文化,因为用户无法控制格式化和解析的完成方式。

【讨论】:

关于最后一点,“很少使用特定的民族文化......”,货币格式会是一个例外吗?例如,如果我有一个包含某个美元值的 Decimal 变量,我是否想破例并在显示它时使用 en-US 作为文化,以确保我不会得到看起来像欧元的数字? I tried CultureInfo.InvariantCulture,但这是为货币标记 ¤ 获取的,所以我不确定这是正确的方法。 @JeffBridgman:我的建议只是一般建议,可能不适用于您的具体情况。但是,我认为您显示小数点(逗号或点)的方式应该是用户控制的(例如使用CultureInfo.CurrentCulture)。如果您除了显示数字之外还需要货币,那么也许您应该以一致的方式执行此操作,即不使用CultureInfo,而是使用三字母货币代码,如USD 1,234.56。这样您就不会陷入将货币映射到文化的问题。 这里有一个问题:InvariantCulture 取决于操作系统,因此不是恒定的。如果您的软件在不同的操作系统上有两个实例,则不应使用 InvariantCulture 在两个实例之间交换字符串。相反,您需要定义一种恒定的文化。 @gawkface:我可能误读了 JohnB 的回答,他说“默认值为 CultureInfo.InstalledUICulture,因此默认 CultureInfo 取决于正在执行的操作系统的设置。”,认为它说的是 Invariantculture 的默认值取决于操作系统。当我的 csv 文件与 Windows 10 German 和 Windows Server 2016 English 上的 InvariantCulture 不同时,我遇到了问题。但也许我有一个不同的错误。 @gawkface 如果您问我,接受的答案不是正确的答案(如果您可以看到,请检查 cmets 和 downvotes)。它已被编辑以删除一些无效信息,但已添加新的无效信息,例如您提到的报价。 CultureInfo.InvariantCulture 是一种固定的文化,它不会因操作系统而异。我相信在比较 Windows 和 Linux 时,文化中存在错误/意外的事情,但如果 CultureInfo.InvariantCulture 受到这些影响,我会感到惊讶。【参考方案3】:

根据微软:

CultureInfo.InvariantCulture 属性既不是中性的也不是 特定的文化。这是第三种文化 文化不敏感。它与英语有关,但 与国家或地区无关。

(来自http://msdn.microsoft.com/en-us/library/4c5zdc6a(vs.71).aspx)

因此,InvariantCulture 类似于“en-US”文化,但并不完全相同。如果你写:

var d = DateTime.Now;
var s1 = d.ToString(CultureInfo.InvariantCulture);   // "05/21/2014 22:09:28"
var s2 = d.ToString(new CultureInfo("en-US"));       // "5/21/2014 10:09:28 PM"

那么 s1 和 s2 将具有相似的格式,但 InvariantCulture 会添加前导零,并且“en-US”使用 AM 或 PM。

因此,当您将日期保存到文本文件或解析数据时,InvariantCulture 更适合内部使用。当您向最终用户提供数据(日期、货币...)时,指定的 CultureInfo 会更好。

【讨论】:

我运行了您的示例代码以确认:InvariantCulture 使用美国 MM/dd/yyyy 而不是遵循 ISO 8601 年份优先格式。尽管如此,它的目的是用于便携式存储和机械加工,而不是供人类消费。多么令人困惑【参考方案4】:

JetBrains 提供合理的explanation,

“数据结构到文本的临时转换很大程度上依赖于 当前的文化,并且可能在代码中导致意想不到的结果 在与本地不同的机器上执行 原开发商。为避免歧义,ReSharper 会警告您任何 代码中可能出现此类问题的实例。”

但如果我在一个我知道只有英文的网站上工作,我会忽略这个建议。

【讨论】:

【参考方案5】:

对于诸如数字(小数点、数量中的逗号)之类的内容,它们通常在特定文化中是首选。

这样做的适当方法是在文化级别(对于德语)进行设置,如下所示:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;

【讨论】:

以上是关于CultureInfo.InvariantCulture 是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章