代码之家  ›  专栏  ›  技术社区  ›  Richard

在.NET中使用十进制类型时出现的问题

  •  4
  • Richard  · 技术社区  · 17 年前

    我在使用.NET和十进制类型时遇到了一个奇怪的问题。我的web应用程序使用以下全球化设置:

    <globalization culture="auto" enableClientBasedCulture="true"/>
    

    在这个场景中,我的应用程序根据检测到的区域性查询一个查找表,并以该货币显示价格。只有当用户做出选择并且准备好将数据发送到我们的支付网关(将123,00欧元转换为123000欧元)时,问题才会出现。

    4 回复  |  直到 14 年前
        1
  •  1
  •   Jim    17 年前

    decimal数据类型基本上只保存一个数字——没有隐式应用于它的格式。数字的值不会因为以不同的格式显示而改变。

    很可能,您可能遇到的问题是,当您从网页接收到字符串形式的输入时,您对其进行了错误的解析。

        2
  •  1
  •   Richard    17 年前

    感谢所有提供经验和建议的人。

    问题在于web配置中的这一行:

    <globalization culture="auto" enableClientBasedCulture="true"/>
    

    设置culture=“auto”允许.NET根据浏览器提供的值设置区域设置(顺便说一句,根据MSDN,“enableClientBasedCulture”未实现,因此您可以忽略它)。因此,如果一位来自法国的访问者(在他们的浏览器中配置了“fr fr”语言)访问我们的网站,那么所有的数字格式都会很好地工作(正确的小数点分隔符和货币符号),但我稍后在尝试将该数字从欧洲格式转换为我所需的英国/美国格式时会遇到问题。

    我实施的解决方案如下:

    1. 使用Decimal.ToString(“c”,ni)-其中“ni”是自定义的NumberFormatInfo类。

    NumberFormatInfo ni = Globalization.CultureInfo.GetCultureInfo("fr-FR").NumberFormat;
    Decimal.ToString("c", ni);
    

    在这个设置中,我的所有十进制值(内部)始终被视为en GB小数,因此采用我需要的格式。换句话说,我的应用程序不需要灵活地更改应用于整个当前线程的设置;恰恰相反:我只关心不同格式的值。

        3
  •  1
  •   Henrik P. Hessel    14 年前

    也许这对你有帮助

            NumberFormatInfo ni = new NumberFormatInfo();
            ni.NumberDecimalSeparator = '.';
    

    用法,即。

            Double.Parse(MyString, ni)
    

    -雷特

    不知道有什么更好的方法来检测格式,但是看看这个

        static void Main(string[] args)
        {
            // German Format (EUR)
            CultureInfo ci_de = new CultureInfo("de-DE");
    
            // English Format (GBP)
            CultureInfo ci_gb = new CultureInfo("en-GB");
    
    
            string test_de = "1.234.567.890,12";
            string test_en = "1,234,567,890.12";
    
            double result_de = 0.0;
            double result_en = 0.0;
    
            try
            {
                result_de = Double.Parse(test_en, ci_de.NumberFormat);
            }
            catch (FormatException ex)
            {
                Console.WriteLine("Number isn't a german format " + ex.InnerException);
            }
            try
            {
                result_en = Double.Parse(test_en, ci_gb.NumberFormat);
            }
            catch (FormatException ex)
            {
                Console.WriteLine("Number isn't a english format " + ex.InnerException);
            }
    
            Console.WriteLine(result_de.ToString());
            Console.WriteLine(result_en.ToString());
    
            Console.ReadLine();
        }
    
        4
  •  0
  •   jrista    17 年前

    rAyt提供了一个良好的开端,但是如果您使用各种文化,那么自动检测十进制数字是哪个文化可能会变得非常困难。为了确保您总是知道,最好围绕包含区域性的decimal创建一个简单的包装器类型。您需要更新数据存储,以同时存储区域性代码(即en US),以便在重建数据时不会“忘记”数据保存为什么区域性。您拥有的任何实体都将使用decimal包装类型,而不是直接使用decimal,并且该类型可以有一个重写的ToString方法,以正确的格式自动呈现:

    public struct CulturedDecimal
    {
        public decimal Value;
        public CultureInfo Culture;
    
        public override ToString()
        {
            return Value.ToString(Culture);
        }
    }
    
    public class SomeEntity
    {
        public int ID { get; set; }
        public CulturedDecimal MonetaryValue { get; set; } // Was 'decimal' before
    }
    
    推荐文章