Ошибка TryParse с отрицательными числами

у меня проблема с тем, чтобы TryParse работал правильно для меня. У меня есть список значений, которые я почти уверен, действительны (поскольку они исходят из другого компонента в нашей системе), но я хотел бы убедиться, что есть правильная обработка ошибок.

вот пример списка моих значений:

20.00
20.00
-150.00

и вот метод, который я первоначально написал:

 private decimal CalculateValue(IEnumerable<XElement> summaryValues)
        {
            decimal totalValue = 0;

            foreach (XElement xElement in summaryValues)
            {
                decimal successful;
                Decimal.TryParse(xElement.Value, out successful);
                if (successful > 0)
                    totalValue += Decimal.Parse(xElement.Value);
            }
            return totalValue;
        }

переменная 'successful' возвращалась false для -150.00, поэтому я добавил NumberStyles:

private decimal CalculateValue(IEnumerable<XElement> summaryValues)
        {
            decimal totalValue = 0;

            foreach (XElement xElement in summaryValues)
            {
                decimal successful;
                Decimal.TryParse(xElement.Value, NumberStyles.AllowLeadingSign, null, out successful);
                if (successful > 0)
                    totalValue += Decimal.Parse(xElement.Value, NumberStyles.AllowLeadingSign);
            }
            return totalValue;
        }

однако теперь, когда у меня есть NumberStyles там, ни одно из чисел не будет разбирать! Я чувствую себя хорошо, имея iformatprovider установлен в null, как это все в нашей системе. Кто-нибудь видит, что я делаю не так?

6 ответов


другие ответы получили правильное представление о правильном способе использования Decimal.TryParse. Однако, если бы я писал рассматриваемый метод, я бы использовал LINQ для работы с объектами LINQ-to-XML:

private decimal CalculateValue(IEnumerable<XElement> summaryValues)
{
    return summaryValues
        .Sum(el =>
             {
                 decimal value;
                 if (Decimal.TryParse(el.Value, out value))
                     return value;
                 return 0M;
             });
}

эта версия работает точно так же, но он использует перечисли.Sum метод для расчета общего числа. Все, что мне нужно предоставить, это встроенная функция, которая извлекает десятичные значения из XElement.


это не то, как вы должны использовать TryParse.

TryParse возвращает логическое значение (true / false), поэтому ваш код выше должен быть:

private decimal CalculateValue(IEnumerable<XElement> summaryValues)
        {
            decimal totalValue = 0;

            foreach (XElement xElement in summaryValues)
            {
                decimal valueReturned;
                bool successful = Decimal.TryParse(xElement.Value, out valueReturned);
                if (successful)
                    totalValue += valueReturned;
            }
            return totalValue;
        }

или просто

private decimal CalculateValue(IEnumerable<XElement> summaryValues)
        {
            decimal totalValue = 0;

            foreach (XElement xElement in summaryValues)
            {
                decimal valueReturned;
                if (Decimal.TryParse(xElement.Value, out valueReturned))
                    totalValue += valueReturned;
            }
            return totalValue;
        }

другие объясняют, как сделать это правильно, но на самом деле не объясняют, что вы делаете неправильно.

где вы используете "успешно" выше, это не значение успеха, это фактическое число, которое анализируется. Поэтому, если вы разбираете "-150.00", конечно, успех будет отрицательным. Значение out TryParse является фактическим анализируемым значением, а логическое значение, указывающее, был ли процесс успешным или нет, является возвращаемым значением. Используя то, что вы должны помочь понять, было бы что-то вроде:

string inputValue = "-150.00";
decimal numericValue;
bool isSucessful = Decimal.TryParse(inputValue , out numericValue);

в этом случае isSuccessful будет TRUE, numericValue будет -150. Когда вы используете пользовательские значения вместо жестко, который я использовал выше, вы захотите проверить:

if(isSuccessful)
{
    // Do something with numericValue since we know it to be a valid decimal
}
else
{
    // Inform User, throw exception, etc... as appropriate, Don't use numericValue because we know it's wrong.
}

ваш успех будет отрицательным для анализируемого отрицательного значения. ваш if (successful > 0) это то, что вас подводит.

если они почти положительно будут действительными значениями, попробуйте использовать Convert.ToDecimal:

decimal val = Convert.ToDecimal(xElement.Value);

в противном случае измените свою логику немного, чтобы быть более похожим:

decimal val;
if (Decimal.TryParse(xElement.Value, out val)){
  // valid number
}

Я бы предложил вам сказать XElement, какое значение узла он должен искать, как в:

XElement.Element("nodename").Value

вместо XElement.Значение. по крайней мере, это то, что я бы сделал :)


пришел из Google. Ответом для меня было то, что входящая культура была неправильной-в частности, во входящем файле JSON.

использовать

totalValue += decimal.Parse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture);

или

bool successful = decimal.TryParse(xElement.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out value);