为什么这个显式转换会抛出“指定的转换无效”异常?
decimal d = 10m;
object o = d;
int x = (int)o;
但是这个可以工作:
int x = (int)(decimal)o;
为什么这个显式转换会抛出“指定的转换无效”异常?
decimal d = 10m;
object o = d;
int x = (int)o;
但是这个可以工作:
int x = (int)(decimal)o;
一个装箱的值只能解箱到完全同样类型的变量中。这个看似奇怪的限制是 .NET 1.x 在泛型还未出现时非常重要的速度优化。你可以在这个答案中阅读更多相关信息。
如果不想跳过多次强制转换,简单值类型实现了 IConvertible 接口。你可以使用 Convert 类来调用该接口:
object o = 12m;
int ix = Convert.ToInt32(o);
当你这样做时,你隐式地将十进制数 d
装箱为一个基本对象:
object o = d;
若要进行强制类型转换,你需要先将装箱后的值拆箱,这也是为什么直接将其强制转换为int会失败的原因:
int x = (int)o;
然而,通过这样做(首先中间转换为十进制):
int x = (int)(decimal)o;
您首先解包o
,这意味着您正在检索十进制值,然后将未打包的十进制值转换为int,这是有效的,因为C#支持将十进制转换为int。
decimal
有一个显式转换运算符到int
。 object
没有:
decimal d = 10m;
object o = d;
int x = (int)d; // OK, calls decimal.explicit operator int(d).
int y = (int)o; // Invalid cast.
这里需要注意的是,装箱和拆箱并不完全是一种转换。你只是把对象类型“围绕”初始的十进制类型“包裹”。这就是为什么在将其转换为整数之前,您需要先进行拆箱。