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】:ToString
和 TryParse
中的文化必须匹配。
要么是
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 - 哪个更快更安全?