【问题标题】:How can I use Convert.ChangeType to convert string into numerics with group separator?如何使用 Convert.ChangeType 将字符串转换为带有组分隔符的数字?
【发布时间】:2010-03-08 11:04:24
【问题描述】:

我想制作一个通用字符串到数字的转换器,并将其作为字符串扩展名提供,所以我编写了以下代码:

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 参数的重载?

【问题讨论】:

    标签: c# generics parsing


    【解决方案1】:

    尝试明确指定文化“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);
        }
    }
    

    Est-ce que ca marche comme ca? :)

    【讨论】:

    • 我尝试了几种文化,但都是一样的:有效的组分隔符的存在会引发 FormatException;尽管它适用于其他事物(小数分隔符、日期和时间分隔符)。对于千位分隔符,您必须指定 NumberStyles.AllowThousands 值。但正如我之前所说,Convert.ChangeType 没有这种参数的重载。
    • 它适用于双精度数,但尝试使用整数:它会失败!以下代码引发格式异常: 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:你是对的,也许 Convert.ChangeType 没有在其实现中指定 NumberStyles.AllowThousands 。您对此无能为力,恐怕您必须自己处理它,而不使用 Convert.ChangeType。
    • 我用 Reflector 验证:Convert.ChangeType 在 IConvertible 上调用 ToInt32()。输入字符串后,IConvertible.ToInt32( ) 完成以 NumberStyles.Integer 作为参数调用 Int32.Parse(...)。 NumberStyles.Integer 不允许千位分隔符; NumberStyles.Number (与 double.Parse 一起使用)允许千位分隔符,这就是解析为 double 工作并解析为 int 失败的原因。我会尝试另一种解决方案...
    猜你喜欢
    • 2011-08-31
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 2022-12-31
    • 1970-01-01
    相关资源
    最近更新 更多