Null coalescing and value type boxing
Try calling this with a null argument.
public double AndCastYeHimIntoAnInt(object o) { return (int) (o ?? 0); }
It works as you would expect; returns 0.0 (implicitly cast from the integer 0).
But we like our casts explicit, so now try this:
public double AndCastYeHimIntoADouble(object o) { return (double) (o ?? 0); }
Woe is me; this fails with an InvalidCastException saying “Specified cast is not valid.”
But heavens, surely the integer zero can be cast to a double? For verily, (double)0 works just fine, and a debugger verifies that that (o ?? 0) indeed evaluates to the integer 0.
But put a watch on (double) (o ?? 0) and quoth the debugger: “Cannot unbox 'o ?? 0' as a 'double'”.
And lo, lift up now thine eyes and place a watch on (o ?? 0).GetType() and it shall prove to be the struct type System.Int32, a boxed integer, and that cannot be cast to a double.
It is a boxed integer unto the LORD, because the compile-time type of the expression must be object, the only type to which both object and int have an implicit conversion.
But why does a boxed integer not convert to Judaism double in the obvious way, by unboxing to int and then implicitly converting to double? Probably because supporting that would require extra work at runtime for every unboxing conversion.
With few exceptions, value-type boxing can be ignored. This is one of those exceptions.