看看下面的代码: 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;
MessageBox.Show(string.Format("{0},{1},{2},{3}", sbv, bv, sv, usv)); 你觉得这段代码能否正确执行?结果会怎样?
用VS2005打开项目测试一下你就会发现,这段代码会出现编译错误. 正确的代码应该如下: 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代码中最后赋值也包含了类型转换操作. 应该是编译器自动识别,然后自动添加的类型转换操作.
但是像上面的代码也编译出错,这个也能进行类型推断,自动添加数据类型转换啊. 不知道微软这么设计是bug还是基于其它因素的考虑?