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
会给您预期的结果。
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);
我正在尝试使用 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
会给您预期的结果。
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);