为什么将double类型转换为decimal类型时会出现InvalidCastException异常?

9
我正在尝试调试一个出现InvalidCastException异常的应用程序。 出错的代码行是:
decimal d = (decimal)row[denominator];

在调试器中检查(见下面的截图),据我所知,行[分母]保存了一个值为8.0的double。那么将其强制转换为decimal不应该有任何问题吧?
('row'类型来自第三方库,该库再次从MySQL的数据中填充。当针对旧的MySQL服务器进行测试时出现问题,该服务器显然返回一些聚合结果作为MySQL 5.1上的double而不是decimal——相同的查询,数据库中完全相同的数据) Visual Studio Screenshot http://img18.imageshack.us/img18/3897/invaldicast.png 请问如何进一步调查此问题?

返回的似乎是一个包含双精度而不是直接双精度的对象。 - Lazarus
8个回答

14

Eric Lippert在他的博客中深入讨论了这个问题。起初我也认为这很不直观,但他解释得很好:Representation and Identity


6

首先需要将row[denominator]转换为double类型,因为它是一个被封装成对象的double类型。

decimal d = (decimal)((double)row[denominator]);

4

row[denominator] 的类型为 object。它包含一个“装箱”的 double。您只能将装箱值转换回其原始类型,然后执行正常的转换。

您可以使用以下方法:

double d1 = (double)row[denominator];
decimal d = (decimal) d1;

当然,您也可以将其缩短为:
decimal d = (decimal) (double)(row[denominator]);

由于需要进行拆箱步骤,您需要进行两个步骤。


4
建议使用Convert.ToDecimal()而不是直接强制转换。

4

我会尝试

decimal d = Convert.ToDecimal(row[denominator]);

或者

decimal d = 0;
if (!decimal.TryParse(row[denominator], out d))
    //do something

2

从错误消息和描述来看,我认为row[denominator]是一个装箱的double类型,因此是object类型。拆箱只能针对正确的基础数据类型进行操作,因为运行时不知道从double到decimal的实际转换运算符在哪里(在您的情况下,它试图查找将object转换为decimal的运算符,但那是一个拆箱运算符,基础类型不是decimal)。因此,正确的方法应该先转换为double,然后再转换为decimal:

decimal d = (decimal)(double)row[denominator];

2

首先尝试将其转换为double类型。由于row[denominator]是装箱的,因此直接转换为decimal类型是行不通的。


0

只需做

decimal d = Convert.ToDecimal(row[denominator]);

这样做,你就不用担心所有的类型转换问题了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接