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, созданную с десятичным разделителем "."