Decimal.TryParse() падает, ведущий "1"

Короткий и сладкий вариант:

На одной машине около ста тестовых машин decimal.TryParse() преобразует "1.01" в 0.01


Хорошо, это будет звучать безумно, но неся со мной...

У нас есть клиентские приложения, которые взаимодействуют с веб-сервисом через JSON, и эта служба возвращает десятичное значение в виде строки, поэтому мы сохраняем его как строку в нашем объекте модели:

[DataMember(Name = "value")]
public string Value { get; set; }

Когда мы отображаем это значение на экране, оно отформатируется на определенное число десятичных знаков. Таким образом, мы используем строку → десятичную, затем десятичную → строку.

В настоящее время приложение проходит окончательное тестирование и работает на более чем 100 машинах, где все работает нормально. Однако на одной машине, если десятичное значение имеет ведущее "1", то оно заменяется нулем. Я добавил простой код в код, чтобы он выглядел следующим образом:

Log("Original string value: {0}", value);
decimal val;
if (decimal.TryParse(value, out val))
{
    Log("Parsed decimal value: {0}", val);
    string output = val.ToString(format, CultureInfo.InvariantCulture.NumberFormat);
    Log("Formatted string value: {0}", output);
    return output;
}

На моей машине - любой другой клиентский компьютер - вывод журнала:

  • Исходное строковое значение: 1.010000
  • Разделимое десятичное значение: 1.010000
  • Отформатированное строковое значение: 1.01

На неисправной машине выход:

  • Исходное строковое значение: 1.010000
  • Разработано десятичное значение: 0.010000
  • Отформатированное строковое значение: 0,01

Итак, кажется, что метод decimal.TryParse ошибочен.

Что мы пробовали:

  • Удаление и переустановка клиентского приложения
  • Удаление и переустановка .net 3.5 sp1
  • Сравнивая региональные параметры дефектных машин для номеров (с использованием английского языка (Соединенное Королевство)) с теми, что работают на рабочем месте, - никаких различий.

Кто-нибудь видел что-нибудь подобное или имеет какие-либо предложения? У меня быстро заканчиваются идеи...


Пока я вводил эту информацию, приходила дополнительная информация: Передача строкового значения "10000" в Convert.ToInt32() возвращает 0, так что также, похоже, выпадет первое.


Дальнейшие тесты, основанные на комментариях:

  • 1.01 → 0.01
  • 111.01 → 11.01
  • 123.01 → 23.01
  • 231.01 → 231.01
  • 01.01 → 1.01

Таким образом, похоже, что это влияет только на 1s и только если они являются первым символом строки. Очень странно, но, по крайней мере, это непротиворечиво.

Ответы

Ответ 1

Я могу воспроизвести ваши результаты. Рассмотрим:

public NumberFormatInfo OneIsPositiveSignFormat()
{
    NumberFormatInfo custom = new NumberFormatInfo();
    custom.PositiveSign = "1";
    return custom;
}

И затем:

if (decimal.TryParse(value, NumberStyles.Number, OneIsPositiveSignFormat(), out val))

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

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

CultureInfo customCulture = (CultureInfo)CultureInfo.InvariantCulture.Clone();
customCulture.NumberFormat = OneIsPositiveSignFormat();
Thread.CurrentThread.CurrentCulture = customCulture;

Ответ 2

посмотреть, как региональные настройки установлены для этого компьютера, возможно, это "." устанавливается как разделитель тысяч не как десятичный разделитель. Попробуйте использовать Decimal.TryParse(String, NumberStyles, IFormatProvider, out Decimal val) и передать NumberFormatInfo, созданную с десятичным разделителем "."