@DanielCasserly Considering that conversion has the same behavior as the constructor I would contend that either the constructor makes that call or is already more efficient.
–
MatthewNov 23 '11 at 20:40

3

@DanielCasserly It has the same semantics as new decimal(double). In fact, it might not be "safer", because Convert.ToDecimal(object) might be selected if we bumbled the object being passed in for some reason.
–
user166390Nov 23 '11 at 20:41

"From what I can tell the only difference is that an explicit cast of a double below Decimal.MinValue returns a zero, while using the constructor throws an OverflowException" I can't reproduce this difference. Casting always gives me an overflow exception, both in release and debug builds, and both in unchecked and checked contexts. Does anyone know what the standard says?
–
JorenNov 23 '11 at 20:52

5 Answers
5

Based on examining the IL with LINQPad, the operator overload is called the same way in checked and unchecked contexts in C#.

In Visual Basic, CDec([double]) and CType([double],Decimal) calls the constructor directly, so there's no difference in that regard, but the cast is more able to participate in compile-time constant-folding than the constructor.

I would rather go for the constructor then! At least you get informed that your value is out of limits instead of setting it to 0 silently!
The documentation says:

The explicit numeric conversion may cause loss of precision or result
in throwing exceptions.

If one does not really care about precision than casting can be used. In the other hand, if you are playing with money for example, the last thing you would do is rounding off doubles! You don't want your application to turn valuable decimal fractions to 0 where you do not expect it to do so.

Edit: See Joren's comment on the main post. This will still throw an exception here in LINQPad 4 (C#4/.NET4) even whenunchecked.

Another option is to use checked (assuming an unchecked context otherwise):

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

Which results in:

OverflowException: Value was either too large or too small for a Decimal.

In the end of the day, however, I think this question is "not a real question" in that which approach is used depends not primarily on the [expected] inputs, but rather, what should happen on an overflow.

I would use the constructor, because that conversion could potentially produce unexpected results due to the difference in precision. It seems logical that the constructor is more prepared to handle the conversion.

As noted in your question there are some circumstances where conversion from double to decimal will result in an OverflowException, which may require some special handling in your code. Casting ignores this exception, which may not be desirable if precision is critical.

Per MSDN, casting can lead to exceptions just as the constructor can. The difference is that casting silently converts to zero if the double is less than Decimal.MinValue whereas the constructor throws.
–
MatthewNov 23 '11 at 20:50

@MatthewPK: Yes, I found the same thing in my research. I've revised my answer accordingly.
–
James JohnsonNov 23 '11 at 20:53

I spoke too soon... apparently the same exceptions are thrown regardless of the method used...
–
MatthewNov 23 '11 at 20:59

Normally I might consider the .TryParse methods but in this case I know that my double can be represented as a decimal. But I don't think parsing the string value of a double is an effective way of making this conversion....
–
MatthewNov 23 '11 at 22:11

1

I see your point. My thing is to avoid exceptions where possible and not let exceptions determine code flow. I have found that cast or Contructors or Converters have this tendancy to throw exceptions when things are not right, so I try to avoid them by using "Try" Methods. In this case using a TryParse means I don't need exception handling in case something goes wrong, see: msdn.microsoft.com/en-us/library/9zbda557.aspx
–
DarrenNov 23 '11 at 23:16