使用InvariantCulture的C#double.TryParse返回意外结果

时间:2017-09-08 05:08:54

标签: c# .net parsing double culture

我正在尝试使用NUnit对getprice方法进行单元测试。我坚持将rawprice解析为double。我的cultureinfo是en-US,但我将其设置为de-DE进行此测试。使用numberstyles.any和invariantculture进行双重解析会返回意外结果。

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

    ...
}

4 个答案:

答案 0 :(得分:7)

从你的问题中不清楚你的期望。但是,就代码所做的而言,它正是按照你所说的去做的:

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

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

如果您不想要该结果,则需要使用不同的参数来调用double.TryParse()。如果您想了解使用哪些参数的建议,您需要解释想要的内容。我们可以说,鉴于您问题中当前的信息,您显然想要的参数。

答案 1 :(得分:4)

您应该将您的文化置于TryParse机制中。

e.g。

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

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

答案 2 :(得分:2)

您将文化设置为de-DE

但显然您决定使用InvariantCulture,而不会将,分隔符识别为小数点分隔符。

使用CurrentCulture代替您将获得预期的结果。

答案 3 :(得分:2)

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);