ACTUALIZACIÓN: Esta cuestión fue the subject of my blog on May 27th 2010. Gracias por la gran pregunta!
Aquí hay muchas respuestas muy confusas. Déjame intentar responder tu pregunta con precisión. Simplifiquemos esto:
object value = whatever;
bool condition = something;
decimal result = (decimal)(condition ? value : 0);
¿Cómo interpreta el compilador la última línea? El problema que enfrenta el compilador es que el tipo de la expresión condicional debe ser coherente para ambas ramas; las reglas de idioma no le permiten devolver el objeto en una rama e int en la otra. Las opciones son object e int. Cada int es convertible a objeto, pero no todos los objetos son convertibles a int, por lo que el compilador elige el objeto. Por lo tanto, esto es lo mismo que
decimal result = (decimal)(condition ? (object)value : (object)0);
Por lo tanto, el cero devuelto es una caja int.
A continuación, destraba la int a decimal. Es ilegal desempaquetar un recuadro int a decimal. Por las razones por las cuales, véase mi artículo de blog sobre el tema:
Representation and Identity
Básicamente, el problema es que estás actuando como si el elenco a decimal se distribuyeron, como esto:
decimal result = condition ? (decimal)value : (decimal)0;
Pero como hemos visto, eso no es lo
decimal result = (decimal)(condition ? value : 0);
medios. Eso significa "convertir ambas alternativas en objetos y luego desempaquetar el objeto resultante".
Quiero aclarar que en las primeras se evalúa a cero y no a DBNull.value. ¿Por qué lanzar 0 a tiros decimales una excepción? – Ioannis