只是在寻找一个解释 - 这个问题几乎解释了这一切,但这里有点额外的:
//this line works OK
int i = Convert.ToInt32(dt.Rows[x]["SmallintColumnName"]);
//this line errors out
int j = (int)dt.Rows[x]["SmallintColumnName"];
我发现这很奇怪,但我想有一个有效的论据,说明为什么会这样。
感谢。
编辑: 您好@Damien_The_Unbeliever - 它是InvalidCastException - 指定的强制转换无效。 我想我需要阅读拳击和拆箱。我认为两者都有效。 现在我刚刚尝试过:
int k = (Int32)r_dtAttribute.Rows[x]["CultureId"];
这也失败了同样的InvalidCastException - 所以任何人都可以告诉我实际的区别是什么
//fails
int k = (Int32)r_dtAttribute.Rows[x]["CultureId"];
和
//works
int i = Convert.ToInt32(dt.Rows[x]["SmallintColumnName"]);
使用(Int32)进行转换时,Convert.ToInt32函数的作用是什么?
由于
答案 0 :(得分:9)
dt.Rows[x]["SmallintColumnName"]
将返回object
。数据库返回的内容实际上已经(由ADO.Net)转换为Int16
1 ,但由于表达式的返回值为object
,因此值为< EM>盒装
我在Boxing and Unboxing上的文章中添加了评论。你的表达:
int j = (int)dt.Rows[x]["SmallintColumnName"];
尝试取消装箱来自object
的值。但是装箱和拆箱的规则说你只能打开与装箱完全相同的类型(除了一些奇怪的规则与枚举及其底层类型,IIRC)。但是,既然我们知道我们拥有的是Int16
盒装,那么您将获得InvalidCastException
。
你能做的是:
int j = (int)(Int16)dt.Rows[x]["SmallintColumnName"];
甚至只是:
int j = (Int16)dt.Rows[x]["SmallintColumnName"];
我们首先取消Int16
值,然后明确(第一个示例)或隐式(第二个)投射 Int16
到{ {1}}。有点不幸的是,铸造和拆箱看起来完全一样。
Int32
是一个完全不同的野兽,支持各种转换。它实际上做的是将参数转换为Convert.ToInt32(object)
接口(IConvertible
支持),然后调用Int16
上的ToInt32
方法。反过来,转而调用Int16
,从已装箱Convert.ToInt32(Int16)
切换回纯Int16
,最终被隐式转换为Int16
。魔法。
1 我已经尝试了,但我认为失败了,在我使用的类型名称的答案中保持一致。但请注意,Int32
和short
的类型完全相同。 Int16
和int
也是相同的类型。因此,将您的尝试从Int32
切换到(int)
并不会导致编译代码发生任何变化。