C# 将包含小数的字符串规范化为特定的CultureInfo.NumberFormat

C# 将包含小数的字符串规范化为特定的CultureInfo.NumberFormat,c#,.net,parsing,decimal,cultureinfo,C#,.net,Parsing,Decimal,Cultureinfo,我正在努力将一个数字标准化为一个特定的CultureInfo,应用它的NumberFormat 假设我有一个字符串,其中也包含一些字符,所以我需要清理它: var cleanedInput = Regex.Replace(userInput, @"[^0-9-,'.]+", ""); 所以我基本上保留了,,和。我这样做是因为根据CultureInfo,和用于分隔小数或分组数字的方式不同 考虑到这一点,我应用了Decimal.TryParse方法,指定NumberStyle以允许使用小数,IFo

我正在努力将一个数字标准化为一个特定的
CultureInfo
,应用它的
NumberFormat

假设我有一个字符串,其中也包含一些字符,所以我需要清理它:

var cleanedInput = Regex.Replace(userInput, @"[^0-9-,'.]+", "");
所以我基本上保留了
。我这样做是因为根据
CultureInfo
,和
用于分隔小数或分组数字的方式不同

考虑到这一点,我应用了
Decimal.TryParse
方法,指定
NumberStyle
以允许使用小数,
IFormatProvider
将被友好地应用于所需的“local”
CultureInfo.NumberFormat

decimal numericData;
if (!decimal.TryParse(cleanedInput, NumberStyles.AllowDecimalPoint, LocaleUser.NumberFormat, out numericData))
    throw new Exception($"Error occurred. Could not parse:{cleanedInput} ");
假设我们输入
“hi9000,99hi”
。清洁后,我们将获得
“9000,99”
。美好的 然后,我们应用
TryParse
,它返回
Decimal
9000.99
。重要的一点是,我实际上是在应用
es es
CultureInfo
,它使用
作为十进制分隔符。我基本上期望
9000,99
9.000,99

代码没有引发
异常
,但看起来它没有应用我指定的
CultureInfo

我到底错过了什么?我觉得Decimal.TryParse是一把瑞士军刀,我处理得很好


非常感谢。使用double.Parse、decimal.Parse或decimal.TryParse似乎很有效。文化信息是如何定义的

string value = "9000,99";
decimal number;
CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES");

try {
    number = decimal.Parse(value, culture);
    decimal.TryParse(value, NumberStyles.Any, culture, out decimal num);
    Console.WriteLine($"{culture.Name}: {value} = {number} / {num}");                       
} catch (FormatException) {
    Console.WriteLine($"{culture.Name}: Unable to parse [{value}]");
}
输出:

es-ES: 9000,99 = 9000.99 / 9000.99

使用double.Parse、decimal.Parse或decimal.TryParse似乎有效。文化信息是如何定义的

string value = "9000,99";
decimal number;
CultureInfo culture = CultureInfo.CreateSpecificCulture("es-ES");

try {
    number = decimal.Parse(value, culture);
    decimal.TryParse(value, NumberStyles.Any, culture, out decimal num);
    Console.WriteLine($"{culture.Name}: {value} = {number} / {num}");                       
} catch (FormatException) {
    Console.WriteLine($"{culture.Name}: Unable to parse [{value}]");
}
输出:

es-ES: 9000,99 = 9000.99 / 9000.99

因此,考虑到小数永远都是小数,并且没有格式,正如在评论中所说的那样,我没有正确地关注问题以及我在搜索什么

我终于使用了这个方法:

private decimal CleanUserInput(string userInput, CultureInfo localeUser)
{
    if (localeUser == null)
        throw new Exception("A CultureInfo must be specified. ");

    var cleanedInput = Regex.Replace(userInput, @"[^0-9-,\.']+", "");
    if (string.IsNullOrWhiteSpace(cleanedInput))
        throw new Exception("Data provided has no numbers to be parsed. ");

    decimal numericData;
    if (!decimal.TryParse(cleanedInput, NumberStyles.Any, localeUser, out numericData))
        throw new Exception($"Couldn't parse {cleanedInput} . Make sure the applied CultureInfo ({LocaleUser.DisplayName}) is the correct one. Decimal separator to be applied: <{LocaleUser.NumberFormat.NumberDecimalSeparator}> Numeric group separator to be applied: <{LocaleUser.NumberFormat.NumberGroupSeparator}>");

    return numericData;
}
private decimal CleanUserInput(字符串userInput,CultureInfo localeUser)
{
if(localeUser==null)
抛出新异常(“必须指定CultureInfo”);
var cleanedInput=Regex.Replace(用户输入,@“[^0-9-,\.]+”,“”);
if(string.IsNullOrWhiteSpace(cleanedInput))
抛出新异常(“提供的数据没有要分析的数字”);
十进制数字数据;
if(!decimal.TryParse(cleanedInput,NumberStyles.Any,localeUser,out numericData))
抛出新异常($”无法分析{cleanedInput}。请确保应用的CultureInfo({LocaleUser.DisplayName})是正确的。要应用的十进制分隔符:要应用的数字组分隔符:“);
返回数值数据;
}

因此,考虑到十进制数始终是十进制数,并且没有格式,正如在评论中所说的那样,我没有正确地关注问题以及我在搜索什么

我终于使用了这个方法:

private decimal CleanUserInput(string userInput, CultureInfo localeUser)
{
    if (localeUser == null)
        throw new Exception("A CultureInfo must be specified. ");

    var cleanedInput = Regex.Replace(userInput, @"[^0-9-,\.']+", "");
    if (string.IsNullOrWhiteSpace(cleanedInput))
        throw new Exception("Data provided has no numbers to be parsed. ");

    decimal numericData;
    if (!decimal.TryParse(cleanedInput, NumberStyles.Any, localeUser, out numericData))
        throw new Exception($"Couldn't parse {cleanedInput} . Make sure the applied CultureInfo ({LocaleUser.DisplayName}) is the correct one. Decimal separator to be applied: <{LocaleUser.NumberFormat.NumberDecimalSeparator}> Numeric group separator to be applied: <{LocaleUser.NumberFormat.NumberGroupSeparator}>");

    return numericData;
}
private decimal CleanUserInput(字符串userInput,CultureInfo localeUser)
{
if(localeUser==null)
抛出新异常(“必须指定CultureInfo”);
var cleanedInput=Regex.Replace(用户输入,@“[^0-9-,\.]+”,“”);
if(string.IsNullOrWhiteSpace(cleanedInput))
抛出新异常(“提供的数据没有要分析的数字”);
十进制数字数据;
if(!decimal.TryParse(cleanedInput,NumberStyles.Any,localeUser,out numericData))
抛出新异常($”无法分析{cleanedInput}。请确保应用的CultureInfo({LocaleUser.DisplayName})是正确的。要应用的十进制分隔符:要应用的数字组分隔符:“);
返回数值数据;
}

我不确定到底是什么问题,但请记住,十进制数没有格式。显示值时提供一种格式-如果在调试器中查看该值,则它将使用计算机设置为的任何区域性。如果要查看特定格式的值,请使用
decimal.ToString
string.format
。因此,您提供的代码会引发异常?在进入解析器之前,
cleanedInput
是您所期望的吗?@Gonzo345再次强调,仅仅因为您使用区域性解析字符串,并不意味着结果值将始终显示在该区域性中。转换为字符串时必须指定区域性,否则将使用系统的区域性。您在谈论什么输出?我希望不是你
numericData
?因为它没有像
或“,”那样的小数分隔符。如果要将该值显示为格式化字符串,请使用您选择的区域设置,这样就可以了。您用于解析的区域设置意味着西班牙用户可以输入“999,99”,而美国人则会在相同的输入中出错。您正在告诉TryParse将输入视为在该语言环境中编写的,以便它能够正确理解。代码工作正常。您没有得到异常和正确的十进制值。解析将字符串转换为数字(或日期时间)。您在VS中看到的是使用PC设置的结果,因此,如果您在美国,您将在以美国格式调试时看到十进制值。我不确定到底是什么问题,但请记住,十进制没有格式。显示值时提供一种格式-如果在调试器中查看该值,则它将使用计算机设置为的任何区域性。如果要查看特定格式的值,请使用
decimal.ToString
string.format
。因此,您提供的代码会引发异常?在进入解析器之前,
cleanedInput
是您所期望的吗?@Gonzo345再次强调,仅仅因为您使用区域性解析字符串,并不意味着结果值将始终显示在该区域性中。转换为字符串或c时,必须指定区域性