Лучше ли приводить double как десятичное или строить «новое» decimal из double? - PullRequest
27 голосов
/ 24 ноября 2011

При переходе от двойного к десятичному, предположим, что мой double может быть представлен как decimal ...

Более уместно ли разыграть двойной какдесятичное число:
( Таблица явных числовых преобразований ) (Обратите внимание, что эта запись ошибочно противоречит первому!)

double foo = bar;
decimal foobar = (decimal)foo;

Или более уместно вызвать конструктор decimal:
( Десятичный конструктор )

double foo = bar;
decimal foobar = new decimal(foo);

Я склонен использовать конструктор decimal, но я удивляюсь, почему нужно использовать одно против другого.

Из того, что я могу сказать, единственное отличие состоит в том, что явное приведение двойного числа ниже Decimal.MinValue возвращает ноль, а при использовании конструктора выдает OverflowException

РЕДАКТИРОВАТЬ: @Joren в комментариях ниже отмечает, что приведение бросает OverflowException и для небольших значений ... так что, очевидно, документация MSDN неверна.

Вопросы, связанные с данной:
- C # приведение двойной переменной к десятичному значению
- Автоматическое приведение от двойного к десятичному: безопасно ли следующее:

Ответы [ 5 ]

18 голосов
/ 24 ноября 2011

Там действительно нет разницы. Использование ILSpy:

// decimal
public static explicit operator decimal(double value)
{
    return new decimal(value);
}

Основываясь на исследовании IL с LINQPad, перегрузка оператора вызывается одинаково в проверенном и непроверенном контекстах в C #.

В Visual Basic, CDec ([double]) и CType ([double], Decimal) вызывают конструктор напрямую, поэтому нет никакой разницы в этом отношении, но приведение в большей степени может участвовать в свертывании констант во время компиляции. чем конструктор.

12 голосов
/ 24 ноября 2011

Я бы лучше пошел за конструктором!По крайней мере, вы получаете уведомление о том, что ваше значение выходит за пределы, вместо того, чтобы устанавливать его на 0 в автоматическом режиме !Документация гласит:

Явное числовое преобразование может вызвать потерю точности или привести к выбрасыванию исключений.

Если на самом деле не важна точность, можно использовать приведение,С другой стороны, если вы играете, например, с деньгами, последнее, что вы должны сделать, - это округлить двойные числа!Вы не хотите, чтобы ваше приложение превращало ценные десятичные дроби в 0, если вы этого не ожидаете.

5 голосов
/ 24 ноября 2011

Редактировать: См. Комментарий Джорена к основному сообщению.Это все равно вызовет исключение здесь, в LINQPad 4 (C # 4 / .NET4) , даже если unchecked.


Другой вариант - использовать checked (при условии контекста unchecked):

double d = double.MaxValue;
decimal f = checked((decimal)d);

Что приводит к:

OverflowException: значение было слишком большим или слишком маленьким для десятичного числа.

В конце концов, однако, я думаю, что этот вопрос "не является реальным вопросом", поскольку тот подход, который используется, зависит не в первую очередь от [ожидаемых] входных данных, а скорее что должно произойти при переполнении .

Удачного кодирования.

3 голосов
/ 24 ноября 2011

Я бы использовал конструктор, потому что это преобразование потенциально может привести к неожиданным результатам из-за разницы в точности. Кажется логичным, что конструктор более подготовлен к обработке преобразования.

Как отмечалось в вашем вопросе, есть некоторые обстоятельства, когда преобразование из двойного в десятичное приведет к OverflowException, что может потребовать некоторой специальной обработки в вашем коде. Приведение игнорирует это исключение, которое может быть нежелательным, если точность критична.

http://msdn.microsoft.com/en-us/library/9sc2bx9h.aspx

1 голос
/ 24 ноября 2011

Можно попробовать так:

double v = 2.33;
decimal b;

if (decimal.TryParse(v.ToString(), out b))
    //do this
else
    //do that
...