C# double.TryParse 与 InvariantCulture returns 意外结果

C# double.TryParse with InvariantCulture returns unexpected result

我正在尝试使用 NUnit 对 getprice 方法进行单元测试。我坚持将原始价格解析为双倍价格。我的 cultureinfo 是 en-US 但我将其设置为 de-DE 用于此测试。使用 numberstyles.any 和不变文化 returns 意外结果进行双重解析。

rawprice cultureinfo 未知,可以是任意值。此外,它将 运行 所在的服务器也是未知的,可以使用任何语言。

对于此测试,我尝试使用德语作为原始价格和机器。

我尝试解析 "9,42" 但结果是 942

[Test]
[SetCulture("de-DE")]
public void GetPrice_PriceTextWithCommaDecimal_ReturnsInvariantPrice()
{
    var rawPriceText = "9,42";
    double.TryParse(rawPriceText, NumberStyles.Any, CultureInfo.InvariantCulture, out double price);
    //parsed price result is 942

    ...
}

你应该把你的文化纳入TryParse机制。

例如

double.TryParse(rawPriceText, NumberStyles.Any, new CultureInfo("de"), out double price);

对于这种情况,您可以使用 CultureInfo.CurrentUICulture 而不是创建新的 CultureInfo

从你的问题中不清楚你的期望是什么。但是,就代码的作用而言,它完全按照您的指示执行:

  • 提供 NumberStyles.Any 告诉 double.TryParse() 允许 任何 格式,AllowHexSpecifier 除外。这包括 AllowThousands 选项。
  • 提供 InvariantCulture 会导致解析使用 ',' 字符作为千位分隔符。
  • 解析实际上并不关心 出现千位分隔符的位置。 IE。它实际上并没有强制分隔符位于指示千位的位置。

因此,当您要求它解析 "9,42" 时,将使用 InvariantCulture 解释该文本(即忽略您当前的 de-DE 文化),',' 字符被视为千位分隔符(即为了计算实际值而被忽略),并且您得到值 942,就像您要求的那样。

如果您不想要该结果,则需要为 double.TryParse() 的调用使用不同的参数。如果您想就 应该 使用的参数提出建议,则需要解释您 做什么 想要什么。鉴于您当前问题中的信息,我们只能说您显然想要什么论点。

您将文化设置为 de-DE

但显然您随后决定改用 InvariantCulture,它不会将 , 分隔符识别为小数点分隔符。

改用 CurrentCulture 会给您预期的结果。

ToStringTryParse 中的文化必须匹配。

可以是

        var s = rawPrice.ToString(CultureInfo.InvariantCulture);
        //rawPrice becomes 9.42
        double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out double price);

        CultureInfo.CurrentCulture = new CultureInfo("de-DE");
        var s= rawPrice.ToString(CultureInfo.CurrentCulture);
        //rawPrice becomes 9,42
        double.TryParse(s, NumberStyles.Any, CultureInfo.CurrentCulture, out double price);