为什么我不能将一个smallint从MSSQL转换为int,如下所示:int x =(int)dt.Rows [x] [“smallIntColumn”]

时间:2014-01-09 11:22:13

标签: c# casting

只是在寻找一个解释 - 这个问题几乎解释了这一切,但这里有点额外的:

//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函数的作用是什么?

由于

1 个答案:

答案 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 我已经尝试了,但我认为失败了,在我使用的类型名称的答案中保持一致。但请注意,Int32short的类型完全相同。 Int16int也是相同的类型。因此,将您的尝试从Int32切换到(int)并不会导致编译代码发生任何变化。