如何使用Convert.ChangeType将带有千位分隔符的字符串转换为数字?

3
我希望能够创建一个通用的字符串转数字转换器,并将其提供为字符串扩展。因此,我编写了以下代码:
public static bool TryParse<T>( this string text, out T result, IFormatProvider formatProvider ) where T : struct
try
{
   result = (T)Convert.ChangeType( text, typeof( T ), formatProvider );
   return true;
}
catch(...

我称之为这样:
int value;
var ok = "123".TryParse(out value, NumberFormatInfo.CurrentInfo)

直到我想使用分组分隔符时,它才能正常工作: 由于我住在法国,千位分隔符是空格,小数分隔符是逗号,因此字符串“1 234 567,89”应等于1234567.89(在不变的文化中)。但是,该函数崩溃了!
当我尝试执行非泛型转换(如double.Parse(...))时,我可以使用一个接受NumberStyles参数的重载。我指定NumberStyles.Number,这次它起作用了!
所以问题是:
- 为什么解析不遵循我的NumberFormatInfo(其中NumberGroupSeparator已正确指定为空格,就像我在我的操作系统中指定的一样)? - 我如何使具有Convert.ChangeTime的通用版本工作,因为它没有接受NumberStyles参数的重载?
1个回答

3

尝试显式指定区域设置为“fr-FR”:

CultureInfo c = new CultureInfo("fr-FR");
double d = 0;
if ("1 234 567,89".TryParse<double>(out d, c)) {
    Console.WriteLine(d);
}

编辑:这个例子可以正常工作:

static class Extension {
    public static bool TryParse<T>(this string text, out T result, IFormatProvider formatProvider) where T : struct {
        result = default(T);
        try {
            result = (T)Convert.ChangeType(text, typeof(T), formatProvider);
            return true;
        } catch {
            return false;
        }
    }

}

class Program {
    static void Main(string[] args) {
        CultureInfo c = new CultureInfo("fr-FR");
        double d = 0;
        // NumberGroupSeparator in fr-FR culture is space
        bool res = "123 456,78".TryParse<double>(out d, c);
        // Set separator as '.' and parse string with dots
        c.NumberFormat.NumberGroupSeparator = ".";
        res = "123.456,78".TryParse<double>(out d, c);
    }
}

这样可以吗?:)

我尝试过几种语言环境,但结果都一样:有效的分组分隔符会引发FormatException异常;虽然它对于其他事情(小数分隔符、日期和时间分隔符)是可行的。对于千位分隔符,您必须指定NumberStyles.AllowThousands值。但正如我之前所说,Convert.ChangeType没有此类参数的重载。 - Loic
它适用于双精度浮点数,但尝试使用整数会失败!以下代码会抛出格式异常: var i = (int)Convert.ChangeType("1 234", typeof(int), new Culture("fr-FR");以下代码有效: var d = (double)Convert.ChangeType("1 234", typeof(double), new Culture("fr-FR"); - Loic
@Loic:你是对的,也许Convert.ChangeType在其实现中没有指定NumberStyles.AllowThousands。恐怕你无能为力,你必须自己处理它,而不能使用Convert.ChangeType。 - Paolo Tedesco
1
我使用Reflector进行验证:Convert.ChangeType在IConvertible上调用ToInt32()。使用字符串作为输入,IConvertible.ToInt32()最终调用Int32.Parse(...)并带有NumberStyles.Integer参数。 NumberStyles.Integer不允许千分位符号;NumberStyles.Number(与double.Parse一起使用)允许千分位符号,这就是为什么解析为double有效而解析为int无效的原因。 我会尝试另一种解决方案... - Loic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接