C# double.TryParse 与 InvariantCulture 返回意外结果

Posted

技术标签:

【中文标题】C# double.TryParse 与 InvariantCulture 返回意外结果【英文标题】:C# double.TryParse with InvariantCulture returns unexpected result 【发布时间】:2017-09-08 05:08:54 【问题描述】:

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

原始价格文化信息是未知的,它可以是任何。此外,它将运行的服务器也是未知的,可以是任何语言。

对于这个测试,我尝试了德语的 rawprice 和 machine。

我尝试解析"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

    ...

【问题讨论】:

【参考方案1】:

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

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

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

如果您不想要该结果,则需要使用不同的参数来调用double.TryParse()。如果您想要应该使用哪些参数的建议,您需要解释您确实想要什么。鉴于目前您问题中的信息,我们只能说您显然想要哪些论据。

【讨论】:

【参考方案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);

【讨论】:

【参考方案3】:

您应该将您的文化放入TryParse 机制中。

例如

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

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

【讨论】:

【参考方案4】:

您将文化设置为de-DE

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

使用CurrentCulture 会得到预期的结果。

【讨论】:

以上是关于C# double.TryParse 与 InvariantCulture 返回意外结果的主要内容,如果未能解决你的问题,请参考以下文章

Double.TryParse 或 Convert.ToDouble - 哪个更快更安全?

无法让 double.TryParse 在 Linq 表达式树中工作

莫名奇妙的异常008:C#中多位小数问题

莫名奇妙的异常008:C#中多位小数问题

如何修复以下 C# 错误?

创建新的 SqlDataAdapter 时出现 C# InvalidOperationException