implicitly convert type 'int' to 'short'的原因与解决方法

所属分类: 网络编程 / ASP.NET 阅读数: 453
收藏 0 赞 0 分享
看看下面的代码:
复制代码 代码如下:

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阶段编译器已经获得了正确的类型信息,那么,在代码生成阶段对变量再进行非良性的类型转换,这也是有保障的设计行为。至此,我相信解释应该完整了...
更多精彩内容其他人还在看

解析WPF实现音频文件循环顺序播放的解决方法

本篇文章是对WPF实现音频文件循环顺序播放的方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

解决.net framework 4.0环境下遇到版本不同编译不通过的方法详解

本篇文章是对.net framework 4.0环境下遇到版本不同编译不通过的解决方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

将文件上传、下载(以二进制流保存到数据库)实现代码

将文件以二进制流的格式写入数据库:首先获得文件路径,然后将文件以二进制读出保存在一个二进制数组中具体请祥看本文,希望对你有所帮助
收藏 0 赞 0 分享

点击提交按钮后DropDownList的值变为默认值实现分析

在点击提交按钮后,页面上所有的绑定到数据库的控件值都恢复到默认值,下面与大家分享下DropDownList的值变为默认值
收藏 0 赞 0 分享

ASP.NET web.config中数据库连接字符串connectionStrings节的配置方法

ASP.NET web.config中数据库连接字符串connectionStrings节的配置方法,需要的朋友可以参考一下
收藏 0 赞 0 分享

Linkbutton控件在项目中的简单应用

Button控件可分为button控件、LinkButton控件、ImageButton控件三类,而LinkButton控件则在页面上显示为一个超级链接,下面与大家分享下其具体应用
收藏 0 赞 0 分享

Web.config 和 App.config 的区别分析

Web.config 和 App.config 的区别分析,需要的朋友可以参考一下
收藏 0 赞 0 分享

基于.Net中的数字与日期格式化规则助记词的使用详解

本篇文章是对.Net中的数字与日期格式化规则助记词的使用进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

解决在Web.config或App.config中添加自定义配置的方法详解

本篇文章是对在Web.config或App.config中添加自定义配置的方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享

深入本机影像生成器(Ngen.exe)工具使用方法详解

本篇文章是对本机影像生成器(Ngen.exe)工具使用方法进行了详细的分析介绍,需要的朋友参考下
收藏 0 赞 0 分享
查看更多