Domanda

Ecco il mio problema (per gli Stati Uniti):

Decimal.Parse (" 1,2,3,4 ") restituisce 1234, invece di lanciare un InvalidFormatException.

La maggior parte delle applicazioni Windows (Excel en-US) non elimina i mille separatori e non considera quel valore un numero decimale. Lo stesso problema si verifica per altre lingue (sebbene con caratteri diversi).

Esistono altre librerie di analisi decimali là fuori che risolvono questo problema?

Grazie!

È stato utile?

Soluzione 2

Ho finito per dover scrivere il codice per verificare manualmente la valuta. Personalmente, per un framework che è orgoglioso di avere tutte le cose della globalizzazione integrate, è sorprendente che .NET non abbia nulla per gestirlo.

La mia soluzione è di seguito. Funziona per tutti i locali nel framework. Non supporta i numeri negativi, come sottolineato da Orion di seguito. Cosa ne pensate ragazzi?

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

Ed ecco un test per dimostrarlo funzionante (nUnit):

<*>

Altri suggerimenti

Ne consente migliaia, poiché il valore NumberStyles predefinito utilizzato da Decimal.Parse ( NumberStyles.Number ) include NumberStyles.AllowThousands .

Se vuoi impedire i migliaia di separatori, puoi semplicemente rimuovere quella bandiera, in questo modo:

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

(il codice sopra genererà un InvalidFormatException , che è quello che vuoi, giusto?)

Potresti riuscire a farlo in un processo in due fasi. Innanzitutto è possibile verificare il separatore delle migliaia utilizzando le informazioni in CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator e CultureInfo.CurrentCulture.NumberFormat.NumberGroupSizes generando un'eccezione se non passa e quindi passare il numero in Decimal.Parse () ;

È un problema comune mai risolto da Microsoft. Quindi, non capisco perché 1,2,3.00 (cultura inglese per esempio) sia valido! È necessario creare un algoritmo per esaminare la dimensione del gruppo e restituire false / exception (come un double.parse non riuscito) se il test non viene superato. Ho avuto un problema simile in un'applicazione mvc, che non è compatibile con validatore incorporato in migliaia ... quindi l'ho sovrascritto con un'usanza personalizzata, usando double / decimal / float.parse, ma aggiungendo una logica per convalidare la dimensione del gruppo.

Se vuoi leggere la mia soluzione (è usata per il mio validatore personalizzato mvc, ma puoi usarlo per avere un validatore generico double / decimal / float.parse migliore) vai qui https://stackoverflow.com/a/41916721/3930528

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top