用GetType()直接测试7为System.Int32
用GetType()直接测试dayCounter为System.UInt32
用GetType()直接测试dayCounter / 7为System.UInt32
因此,原因同我上面所述,我还是不清楚为什么?
用GetType()直接测试dayCounter为System.UInt32
用GetType()直接测试dayCounter / 7为System.UInt32
因此,原因同我上面所述,我还是不清楚为什么?
C#编译器还是很聪明的,7可以转换成uint,所以...
6.1.6 Implicit constant expression conversions
An implicit constant expression conversion permits the following conversions:
A constant-expression (Section 7.15) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.
n = n + 2;
这样会报错: 无法将类型“int”隐式转换为“byte”。
从这里可以知道编译器并没有把2转换成为byte型(事实上2也确实在byte数据类型范围之内)再和n去相加,而是直接用了其int类型,这样整个表达式(n + 2)的结果将成为int,因此会有上面的报错提示,这又如何解释呢?
如果是范围大的向范围小的转换可能存在溢出,系统会报错。
byte n=10;n=n+2;
2是int 转换时byte会超出范围
相反小到大范围的转换系统会通过。
你提到的情况在隐式转换变量时确实如此,但是对于像100这样的字面值,C#编译器可能并不是这样处理的,如上面我提到的问题:
uint weeks;
uint dayCounter = 14;
weeks = dayCounter / 7;
这里编译器通过,这说明7会被隐式转换成了uint,而在这里7是做为int类型出现的,而int是不会隐式转换成uint类型的,所以... ...
6.1.6 Implicit constant expression conversions
只提到了int和long可以参与这样的受限制的隐式常量类型转换,byte不行,所以编译报错。从CLR的工作原理来讲,CLR只支持至少32位的运算,所以byte在运算之前需要线转换成int。
long 类型的常数表达式可以转换为 ulong 类型(前提是常数表达式的值不为负)。
如上所述:
byte n = 10;
n = n + 2;
这里2从字面值角度应该是int型吧,为什么它不可以自动隐式转换成byte类型呢?而且它也确实在byte范围之内!对于这个问题,我不认为是钻牛角尖,花小部分时间把一门语言的数据类型及其转换想清楚,这对于我们今后的编程是大有好处的,难道每次我们写类似这样的处理时,如n = n + 2。都要先试一试,看编译器能否通过,如果不能通过再强制转换吗?:-)
C# Language Specification
7.2.6.1 Unary numeric promotions
7.2.6.2 Binary numeric promotions
讲了运算过程中的类型转换问题。我前面说了,由于CLR实现的限制,C#中所有的运算至少是32位的。所以即使两个byte相加,结果也一定是int。>> 对于这个问题,我不认为是钻牛角尖,花小部分时间把一门语言的数据类型及其转换想清楚,这对于我们今后的编程是大有好处的,难道每次我们写类似这样的处理时,如n = n + 2。都要先试一试,看编译器能否通过,如果不能通过再强制转换吗?:-)至少,我个人在这个问题上是以来编译器的。:)
但是,对于6.1.6 隐式常数表达式转换 中提到的:
隐式常数表达式转换允许进行以下转换: int 类型的常数表达式(第 7.15 节)可以转换为 sbyte、byte、short、ushort、uint 或 ulong 类型(前提是常数表达式的值在目标类型的范围内)。
long 类型的常数表达式可以转换为 ulong 类型(前提是常数表达式的值不为负)。
如果如你所述:“由于CLR实现的限制,C#中所有的运算至少是32位的”,那么为什么微软又允许将int类型的常数表达式在范围允许之内可以转向如byte等低于32位的数据类型呢?请举例解释,指点一二,谢!
public void MyTest(byte b) {
...
}
}...
Test t = new Test();
t.MyTest(5); //这里的5需要隐式转换成byte
...