源码网,源码论坛,源码之家,商业源码,游戏源码下载,discuz插件,棋牌源码下载,精品源码论坛

 找回密码
 立即注册
查看: 53|回复: 20

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

[复制链接]

7万

主题

861

回帖

32万

积分

论坛元老

Rank: 8Rank: 8

积分
329525
发表于 2009-6-13 20:40:56 | 显示全部楼层 |阅读模式
implicitly convert type 'int' to 'short'的原因与解决方法 看看下面的代码:
复制代码 代码如下:
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阶段编译器已经获得了正确的类型信息,那么,在代码生成阶段对变量再进行非良性的类型转换,这也是有保障的设计行为。至此,我相信解释应该完整了...
回复

使用道具 举报

0

主题

2万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2022-9-6 07:38:20 | 显示全部楼层
66666666666666666666
回复 支持 反对

使用道具 举报

3

主题

2万

回帖

156

积分

注册会员

Rank: 2

积分
156
发表于 2023-3-4 15:02:41 | 显示全部楼层
66666666666666666666
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

120

积分

注册会员

Rank: 2

积分
120
发表于 2023-5-3 18:18:07 | 显示全部楼层
啦啦啦啦啦德玛西亚
回复 支持 反对

使用道具 举报

5

主题

2万

回帖

183

积分

注册会员

Rank: 2

积分
183
发表于 2023-7-19 18:59:20 | 显示全部楼层
。。。。。。。。。。。。。。。
回复 支持 反对

使用道具 举报

0

主题

1万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2023-9-28 15:02:44 | 显示全部楼层
好东西一定要看看!
回复 支持 反对

使用道具 举报

0

主题

1万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2023-10-1 13:14:30 | 显示全部楼层
看到这帖子真是高兴!
回复 支持 反对

使用道具 举报

2

主题

2万

回帖

380

积分

中级会员

Rank: 3Rank: 3

积分
380
发表于 2023-10-6 12:24:04 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

2

主题

2万

回帖

381

积分

中级会员

Rank: 3Rank: 3

积分
381
发表于 2024-4-10 21:13:32 | 显示全部楼层
你们谁看了弄洒了可能
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2024-4-14 11:19:16 | 显示全部楼层
强烈支持楼主ing……
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

手机版|小黑屋|网站地图|源码论坛 ( 海外版 )

GMT+8, 2024-11-25 06:35 , Processed in 0.075787 second(s), 26 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表