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

时间:2009-05-22 10:49:36

标签: .net globalization

我对.NET有一点奇怪的问题,并使用十进制类型。我的Web应用程序使用以下全球化设置:

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

考虑到这一点,请考虑以下因素:小数值123.00英镑为123.00英镑,欧元为123,00(注意逗号)。当我想从123,000(EUR)的十进制值再次回到GBP时,我出现的问题就变成了123,000 - 这是一个很大的问题。

在这种情况下,我的应用程序根据检测到的文化查询了一个查找表,并显示该货币的价格。只有当用户做出选择并且数据准备好发送到我们的支付网关时才会出现问题,支付网关将123,00欧元转换为123,000。

我有什么想法可以解决这个问题?

4 个答案:

答案 0 :(得分:1)

也许这可以帮到你

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

用法即

        Double.Parse(MyString, ni)

-rAyt

不知道有什么更好的方法来检测格式,但请看一下

    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();
    }

答案 1 :(得分:1)

十进制数据类型基本上只包含一个数字 - 没有隐式应用的格式。数字的值不会因为它以不同的格式显示而改变。

可能,您可能遇到的问题是当您从网页收到输入为字符串时,您正在解析它。

答案 2 :(得分:1)

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

实现一个自定义类型/结构来保存我自己的Decimal值并不是我真正想要的,并且不会真正给我我需要的功能(我已经可以以适当的本地货币/格式显示十进制值,我无法在需要时将它们转换回英国格式。

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

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

设置culture =“auto”允许.NET根据浏览器提供的值设置语言环境(顺便提一下,根据MSDN,'enableClientBasedCulture'没有实现 - 所以你可以省略它)。因此,如果来自法国的访问者(在他们的浏览器中配置了语言'fr-FR')访问我们的网站,所有数字格式将完美地工作(正确的小数点分隔符和货币符号),但我在以后尝试时遇到问题将这个数字从它的欧洲格式转换为我要求的英国/美国格式。

这很奇怪,但将“123.00”转换为“fr-FR”语言环境会产生FormatException,因为“123.00”在法语区域设置中无效(它需要“123,00”)。但是,将“123,00”(fr-FR)转换为英国/美国“en-GB”或“en-US”格式不会产生错误,而是将值变为“123,000”。我相信这应该抛出一个FormatException,因为添加另一个零是不可接受的。

我实施的解决方案如下:

  1. 在web.config中将culture =“auto”设置为culture =“en-GB”。
  2. 使用Decimal.ToString(“c”,ni) - 其中'ni'是自定义NumberFormatInfo类。
  3. 由于我的现有代码连接到我们的数据源以检索依赖于国家/地区的正确小数值,因此我现在所有的都是格式化问题。因此,要根据'fr-FR'区域设置格式化数字,您可以执行以下操作:

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

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

答案 3 :(得分:0)

rAyt提供了一个良好的开端,但如果您正在使用各种文化,则可能很难自动检测十进制数是哪种文化。为了确保您始终知道,最好在包含文化的小数周围创建一个简单的包装器类型。您需要更新数据存储以存储文化代码(即en-US),以便在重构数据时您不会“忘记”数据保存的文化。您拥有的任何实体都将使用您的小数包装器类型,而不是直接使用小数,并且该类型可以使用重写的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
}