Pregunta

Aquí está mi problema (para en-US):

Decimal.Parse (" 1,2,3,4 ") devuelve 1234, en lugar de lanzar una InvalidFormatException.

La mayoría de las aplicaciones de Windows (Excel en-US) no eliminan los miles de separadores y no consideran ese valor un número decimal. El mismo problema ocurre para otros idiomas (aunque con caracteres diferentes).

¿Hay alguna otra biblioteca de análisis decimal que resuelva este problema?

¡Gracias!

¿Fue útil?

Solución 2

Terminé teniendo que escribir el código para verificar la moneda manualmente. Personalmente, para un marco que se enorgullece de tener todo el material de globalización incorporado, es increíble .NET no tiene nada para manejar esto.

Mi solución está abajo. Funciona para todas las configuraciones regionales en el marco. Sin embargo, no admite números negativos, como Orion señaló a continuación. ¿Qué piensan ustedes?

    public static bool TryParseCurrency(string value, out decimal result)
    {
        result = 0;
        const int maxCount = 100;
        if (String.IsNullOrEmpty(value))
            return false;

        const string decimalNumberPattern = @"^\-?[0-9]{{1,{4}}}(\{0}[0-9]{{{2}}})*(\{0}[0-9]{{{3}}})*(\{1}[0-9]+)*
    [Test]
    public void TestCurrencyStrictParsingInAllLocales()
    {
        var originalCulture = CultureInfo.CurrentCulture;
        var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
        const decimal originalNumber = 12345678.98m;
        foreach(var culture in cultures)
        {
            var stringValue = originalNumber.ToCurrencyWithoutSymbolFormat();
            decimal resultNumber = 0;
            Assert.IsTrue(DecimalUtils.TryParseCurrency(stringValue, out resultNumber));
            Assert.AreEqual(originalNumber, resultNumber);
        }
        System.Threading.Thread.CurrentThread.CurrentCulture = originalCulture;

    }
quot;; NumberFormatInfo format = CultureInfo.CurrentCulture.NumberFormat; int secondaryGroupSize = format.CurrencyGroupSizes.Length > 1 ? format.CurrencyGroupSizes[1] : format.CurrencyGroupSizes[0]; var r = new Regex(String.Format(decimalNumberPattern , format.CurrencyGroupSeparator==" " ? "s" : format.CurrencyGroupSeparator , format.CurrencyDecimalSeparator , secondaryGroupSize , format.CurrencyGroupSizes[0] , maxCount), RegexOptions.Compiled | RegexOptions.CultureInvariant); return !r.IsMatch(value.Trim()) ? false : Decimal.TryParse(value, NumberStyles.Any, CultureInfo.CurrentCulture, out result); }

Y aquí hay una prueba para demostrar que funciona (nUnit):

<*>

Otros consejos

Está permitiendo miles, porque el valor predeterminado de NumberStyles utilizado por Decimal.Parse ( NumberStyles.Number ) incluye NumberStyles.AllowThousands .

Si desea no permitir los separadores de miles, puede eliminar esa bandera, así:

Decimal.Parse("1,2,3,4", NumberStyles.Number ^ NumberStyles.AllowThousands)

(el código anterior arrojará una InvalidFormatException , que es lo que quieres, ¿verdad?)

Es posible que pueda hacer esto en un proceso de dos fases. Primero, puede verificar el separador de miles utilizando la información en CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator y CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes lanzando una excepción si no pasa y luego pasa el número al Decimal.Parse () ;

Es un problema común que Microsoft nunca resuelve. Entonces, no entiendo por qué 1,2,3.00 (por ejemplo, la cultura inglesa) es válida. Debe crear un algoritmo para examinar el tamaño del grupo y devolver falso / excepción (como un double.parse fallido) si no se pasa la prueba. Tuve un problema similar en una aplicación mvc, que el validador de compilación no acepta miles ... así que lo he sobrescrito con una costumbre, usando double / decimal / float.parse, pero agregando una lógica para validar el tamaño del grupo.

Si desea leer mi solución (se usa para mi validador personalizado mvc, pero puede usarlo para tener un mejor validador genérico doble / decimal / float.parse) vaya aquí https://stackoverflow.com/a/41916721/3930528

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top