为什么我不能像这样将 smallint 从 MSSQL 转换为 int:int x = (int)dt。行[x][ "smallIntColumn" ]



只是想对此进行解释-这个问题几乎解释了一切,但这里有一点额外:

//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"]);

Convert.ToInt32函数的作用是什么?

感谢

dt.Rows[x]["SmallintColumnName"]将返回一个object。数据库返回的内容实际上已被ADO.Net翻译成Int161,但由于表达式的返回值是object,因此该值已被装箱

我在一篇评论中链接到了关于拳击和解包的文章。你的表情:

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强制转换为Int32。有点不幸的是,选角和开箱看起来完全一样。

Convert.ToInt32(object)是一个完全不同的野兽,支持各种转换。它实际做的是将参数强制转换为IConvertible接口(Int16支持该接口),然后在Int16上调用ToInt32方法。反过来,它反过来调用Convert.ToInt32(Int16),从盒装的Int16切换回纯Int16,最终隐式转换为Int32。魔术


1我尝试过,但我认为失败了,在我使用的类型名称中,在整个答案中保持一致。但要注意,shortInt16是完全相同的类型。CCD_ 22和CCD_。因此,将尝试从(int)切换到(Int32)实际上并没有导致编译代码发生任何更改。

最新更新