Лучше ли использовать двойную цифру как десятичную или построить "новый" десятичный знак из двойника?
При переходе от двойного к десятичному, предполагая, что мой double
может быть представлен как decimal
...
Уместнее ли использовать двойное число как десятичное:
(Явная таблица числовых преобразований) (Обратите внимание, что эта запись ошибочно противоречит первому!)
double foo = bar;
decimal foobar = (decimal)foo;
Или более целесообразно называть конструктор decimal
:
(Десятичный конструктор)
double foo = bar;
decimal foobar = new decimal(foo);
Я склонен использовать конструктор decimal
, но я удивляюсь, почему он использует один и тот же.
Из того, что я могу сказать, единственное различие заключается в том, что явный листинг двойника ниже Decimal.MinValue
возвращает ноль, а при использовании конструктора выбрасывается OverflowException
EDIT: @Joren в комментариях ниже отмечает, что бросок бросает OverflowException
для небольших значений... так что, по-видимому, документация MSDN неверна.
Вопросы, относящиеся:
- С# перевести двойную переменную в десятичную
- Автоматически отбрасывать с двойного на десятичный: безопасно ли следующее:
Ответы
Ответ 1
Там действительно нет разницы. Использование ILSpy:
// decimal
public static explicit operator decimal(double value)
{
return new decimal(value);
}
Исходя из изучения IL с LINQPad, перегрузка оператора вызывается таким же образом в проверенных и непроверенных контекстах на С#.
В Visual Basic CDec ([double]) и CType ([double], Decimal) вызывает конструктор напрямую, поэтому нет никакой разницы в этом отношении, но литье более способно участвовать во временном сгибании времени компиляции чем конструктор.
Ответ 2
Я бы лучше пошел за конструктором! По крайней мере, вы узнаете, что ваше значение вне пределов, вместо того, чтобы устанавливать его на 0 молча!
В документации указано:
Явное числовое преобразование может привести к потере точности или результату в метании исключений.
Если вам не нужна точность, отличная от литья, можно использовать. С другой стороны, если вы играете с деньгами, например, последнее, что вы делаете, это округление вдвое! Вы не хотите, чтобы ваше приложение превращало ценные десятичные дроби в 0, если вы этого не ожидаете.
Ответ 3
Изменить: см. комментарий Джорана на главный пост. Это все равно вызовет исключение здесь, в LINQPad 4 (С# 4/.NET4), даже если unchecked
.
Другой вариант - использовать checked
(при условии, что в контексте unchecked
):
double d = double.MaxValue;
decimal f = checked((decimal)d);
Результат:
OverflowException: значение было слишком большим или слишком маленьким для десятичного числа.
В конце дня, однако, я думаю, что этот вопрос "не является реальным вопросом" в том, что используемый подход зависит не в основном от [ожидаемых] входов, а скорее от того, что должно произойти при переполнении.
Счастливое кодирование.
Ответ 4
Я бы использовал конструктор, потому что это преобразование потенциально может привести к неожиданным результатам из-за разницы в точности. Кажется логичным, что конструктор более подготовлен к обработке преобразования.
Как отмечено в вашем вопросе, есть некоторые обстоятельства, при которых преобразование из double в decimal приведет к OverflowException
, что может потребовать некоторой специальной обработки в вашем коде. Кастинг игнорирует это исключение, что может быть нежелательно, если точность критическая.
http://msdn.microsoft.com/en-us/library/9sc2bx9h.aspx
Ответ 5
Мог бы попробовать следующее:
double v = 2.33;
decimal b;
if (decimal.TryParse(v.ToString(), out b))
//do this
else
//do that