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