当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > implicitly convert type ''int'' to ''short''的原因与解决方法

ASP.NET
ASP.NET开发:简化应用程序的开发支持Web标准
asp.net XMLHttpRequest实现用户注册前的验证
asp.net 页面间传值方法小结
asp.net url重写浅谈
asp.net 验证码生成和刷新及验证
C#精髓 GridView72大绝技 学习gridview的朋友必看
实例说明asp.net中的简单角色权限控制
asp.net网站开发包wq.dll打包下载
js与ASP.NET 中文乱码问题
asp.net checkbox 动态绑定id GridView删除提示
asp.net TextBox回车触发事件 图片在img显示
asp.net 脏字典过滤问题 用正则表达式来过滤脏数据
asp.NET 脏字过滤算法
asp.NET 脏字过滤算法 修改版
asp.net sql 数据库处理函数命令
asp.net Javascript 的几种写法与提示
ASP.NET MVC学习笔记
asp.net 中国身份证号码验证代码 非正则
Asp.net中使用Sqlite数据库的方法
asp.net 中文字符串提交乱码的解决方法

ASP.NET 中的 implicitly convert type ''int'' to ''short''的原因与解决方法


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-13   浏览: 213 ::
收藏到网摘: n/a

看看下面的代码:
复制代码 代码如下:

sbyte sba, sbb,sbv;
sba = 1;
sbb = 2;
sbv = sba + sbb;
byte ba, bb, bv;
ba = 1;
bb = 2;
bv = ba + bb;
short sa, sb, sv;
sa = 1;
sb = 2;
sv = sa + sb;
ushort usa, usb, usv;
usa = 1;
usb = 2;
usv = usa + usb;

你觉得这段代码能否正确执行?结果会怎样? 结果就是:这段代码会出现编译错误.
正确的代码应该如下:
复制代码 代码如下:

sbyte sba, sbb,sbv;
sba = 1;
sbb = 2;
sbv = (sbyte)(sba + sbb);
byte ba, bb, bv;
ba = 1;
bb = 2;
bv = (byte)(ba + bb);
short sa, sb, sv;
sa = 1;
sb = 2;
sv = (short)(sa + sb);
ushort usa, usb, usv;
usa = 1;
usb = 2;
usv = (ushort)(usa + usb);
MessageBox.Show(string.Format("{0},{1},{2},{3}", sbv, bv, sv, usv));

这是什么原因呢?
其实CLR底层只支持 int,int64,native int, float , double几种数据类型. 像上面的sbyte,byte,short,ushort, clr底层是不支持的,在底层这些类型是用int表示的. CLR的堆栈中压入的数字,最小是4字节,小于4字节的会根据其类型进行符号扩展或者0扩展为4字节int型. 这样四则运算的结果也是int型,最后再赋值需要进行强制类型转换. 分析一下编译后的IL代码就清楚了.
下面这个代码为什么能编译呢?
复制代码 代码如下:

short sb;
sb=2;
sb += 1;

其实编译后的IL代码中最后赋值也包含了类型转换操作.

看下更加详细的解释:

复制代码 代码如下:

short s=0;
s = s + 1; //报错,右端是复杂表达式,1被解释成int
s+=1; //不报错,1被解释成short, 请看下面的解释
s += 32768; //报错,显然32768是不能解释成short的,只能解释成int
s+=(s+1); //报错,右端是复杂表达式,1被解释成int

从上面可以看出一个规则,那就是,复杂表达式计算中的隐式良性类型转换,一概默认直接解释或转换成4字节对齐的CLS兼容类型,如int/long,理由很简单:既省了麻烦,又能保证性能(不仅有运行效率时的考虑,而且还有代码生成的考虑,因此这种考虑是一步到位的),例如,s=s+1中的1,被解释成了int,而不是short,这是合理的。但如果不是复杂表达式,而仅仅只是一个简单的常数量的话,编译器在parse时便不会遵循"4字节对齐的CLS兼容类型",它将根据其他部分来自动判别最适合的类型(这种做法也是合理的,因为此时仍处于parse阶段,迅速判断类型是否兼容才是第一要务,性能不性能、对不对齐是次要问题,所以,此时对数字常量的类型解释也用不着一步到位,遵循最快最省事原则即可...),比方说s+=1和s+=32768这两个例子,前者1被解释成short,所以合法,后者32768将被迫解释成int,左右式类型不兼容,所以出错。同理,上述解释也适用于s+=(s+1)这个例子:(s+1)是复杂表达式,不是简单数字常量,所以被解释成(int)s+(int)1,而不是(short)s+(short)1,从而报错。
请注意上述解释主要针对parse阶段。实际上,到了代码生成阶段,出于性能等目的,类型可能还会得到进一步提升,如s+=1这个例子,实际上在IL代码生成阶段,这个parse阶段识别出来的(short)1最终被提升为了(int)1,这应该便是瑞克观察到的IL参数4字节对齐的现象了。其实,为避免混淆,我觉得一般使用者理解到parser层面便足矣,因为类型的判别和兼容性检查在代码生成阶段已经不是关键问题了,不过当然,只要是良性类型提升,无论哪个阶段都是可以做的,甚至,只要在parse阶段编译器已经获得了正确的类型信息,那么,在代码生成阶段对变量再进行非良性的类型转换,这也是有保障的设计行为。至此,我相信解释应该完整了...