为什么不能将MSSQL的smallint强制转换为int:int x =(int)dt.Rows [x] [“ smallIntColumn”] [英] Why can I not cast a smallint from MSSQL to int like this: int x = (int)dt.Rows[x]["smallIntColumn"]

查看:153
本文介绍了为什么不能将MSSQL的smallint强制转换为int:int x =(int)dt.Rows [x] [“ smallIntColumn”]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是在寻找一个解释-这个问题几乎可以解释所有问题,但是还有一点额外的地方:

  //这行有效OK 
int i = Convert.ToInt32(dt.Rows [x] [ SmallintColumnName]));

//此行错误
int j =(int)dt.Rows [x] [ SmallintColumnName];

我觉得很奇怪,但是我想对于为什么会这样有一个有效的论据。



谢谢。



编辑:
嗨@Damien_The_Unbeliever-这是一个InvalidCastException-指定的转换无效。
我想我需要阅读有关装箱和拆箱的信息。我以为两者都可以。
现在我刚刚尝试过:

  int k =(Int32)r_dtAttribute.Rows [x] [ CultureId ]; 

这也会因相同的InvalidCastException而失败-谁能告诉我两者之间的实际区别是什么

  //失败
int k =(Int32)r_dtAttribute.Rows [x] [ CultureId];

  // works 
int i = Convert.ToInt32(dt.Rows [x] [ SmallintColumnName]);

仅使用(Int32)进行转换的Convert.ToInt32函数有什么作用? / p>

谢谢

解决方案

dt.Rows [ x] [ SmallintColumnName] 将返回对象。返回的数据库实际上已经(通过ADO.Net)转换为 Int16 1 ,但是由于表达式的返回值为 object ,该值已被装箱



我在评论中链接了有关装箱和拆箱。您的表达式:

  int j =(int)dt.Rows [x] [ SmallintColumnName]; 

尝试从拆箱一个值>对象。但是装箱和拆箱规则说,您只能将与装箱的类型完全拆箱(除了一些与枚举及其基本类型IIRC有关的怪异规则)。但是,由于我们知道所拥有的是装箱的 Int16 ,因此您将获得 InvalidCastException



您可以做的是:

  int j =(int)( Int16)dt.Rows [x] [ SmallintColumnName]; 

甚至只是:

  int j =(Int16)dt.Rows [x] [ SmallintColumnName]; 

我们在哪里 first 取消对 Int16的装箱值,然后显式(第一个示例)或隐式(第二个) cast Int16 转换为 Int32 。不幸的是,投射和取消装箱看上去完全一样。



Convert.ToInt32(object)完全不同野兽并支持各种转化。它的实际作用是将参数转换为 IConvertible 接口( Int16 支持),然后调用<$ Int16 上的c $ c> ToInt32 方法。依次转过来并调用 Convert.ToInt32(Int16),从装箱的 Int16 只是一个普通的 Int16 ,最终将其隐式转换为 Int32 。魔术。






1 我尝试过,但我认为失败了,在整个过程中保持一致我使用的类型名称中的答案。但是请注意, short Int16 是完全相同的类型。 int Int32 也是相同的类型。因此,将您的尝试从(int)切换为(Int32)实际上并不会导致编译后的代码发生任何变化。


Just looking for an explanation on this - the question pretty much explains it all but here's an bit extra:

//this line works OK
int i = Convert.ToInt32(dt.Rows[x]["SmallintColumnName"]);

//this line errors out
int j = (int)dt.Rows[x]["SmallintColumnName"];

I find this strange but I guess there's a valid argument on why this is like it is.

Thanks.

EDIT: Hi @Damien_The_Unbeliever - it is an InvalidCastException - Specified cast is not valid. I guess I need to read up on boxing and unboxing. I assumed that both would work. Now I have just tried:

int k = (Int32)r_dtAttribute.Rows[x]["CultureId"];

this also fails with the same InvalidCastException - so can anyone tell me what the actual difference is between

//fails
int k = (Int32)r_dtAttribute.Rows[x]["CultureId"];

and

//works
int i = Convert.ToInt32(dt.Rows[x]["SmallintColumnName"]);

What does the Convert.ToInt32 function do that just casting with (Int32) doesn't do?

Thanks

解决方案

dt.Rows[x]["SmallintColumnName"] is going to return an object. What the database returned has actually been translated (by ADO.Net) into an Int161, but since the return value of the expression is object, the value has been boxed.

I linked in a comment to the article on Boxing and Unboxing. Your expression:

int j = (int)dt.Rows[x]["SmallintColumnName"];

Is an attempt to unbox a value from an object. But the rules of boxing and unboxing say that you can only unbox exactly the same type that was boxed (except some weird rules to do with enums and their underlying types, IIRC). But since we know that what we have is a boxed Int16, you're going to get an InvalidCastException.

What you could do is:

int j = (int)(Int16)dt.Rows[x]["SmallintColumnName"];

or even just:

int j = (Int16)dt.Rows[x]["SmallintColumnName"];

Where we first unbox the Int16 value and then explicitly (first example) or implicitly (second) cast the Int16 to an Int32. It's slightly unfortunate that casting and unboxing look exactly the same.

Convert.ToInt32(object) is a whole different beast and supports all kinds of conversions. What it actually does is to cast the argument to the IConvertible interface (which Int16 supports) and then calls the ToInt32 method on the Int16. That, in turn, turns around and calls Convert.ToInt32(Int16), having switched back from being a boxed Int16 to just being a plain Int16, which finally gets implicitly converted into an Int32. Magic.


1 I've tried, but I think failed, to be consistent throughout the answer in the type names I use. But be aware that short and Int16 are exactly the same type. int and Int32 are also the same types. So switching your attempt from (int) to (Int32) didn't actually cause any change in the compiled code.

这篇关于为什么不能将MSSQL的smallint强制转换为int:int x =(int)dt.Rows [x] [“ smallIntColumn”]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆