gdo*_*ica 15 .net c# compiler-construction types
为什么编译器决定2.3是double,所以这段代码不能编译:
decimal x;
x = 2.3; // Compilation error - can not convert double to decimal.
x = (decimal) 2.3 // O.k.
Run Code Online (Sandbox Code Playgroud)
为什么编译器不这样想:
他想得到一个小数,他给我一个可以是十进制的值,所以它是十进制的!
为什么这不会出现编译错误:
short x;
x = 23; // O.K.
Run Code Online (Sandbox Code Playgroud)
谁说23不是int?
Eri*_*ert 23
这里有很多问题.让我们把它们分解成小问题.
为什么文字2.3的类型是double而不是decimal?
历史原因.C#被设计为"类C语法"系列语言的成员,因此其表面外观和基本习语对于使用类C语言的程序员来说是熟悉的.在几乎所有这些语言中,浮点文字被视为二进制而不是十进制浮点数,因为这就是C最初的做法.
如果我从零开始设计一种新语言,我可能会使含糊不清的文字变得非法; 每个浮点字面值都必须是非负的,单个或十进制,依此类推.
为什么在double和decimal之间隐式转换一般是非法的?
因为这样做可能是一个错误,有两种方式.
首先,双精度和小数具有不同的范围和不同的"表示错误"量 - 也就是说,从您希望表示的精确数学量实际表示的数量有多么不同.将双精度转换为十进制或反之亦然是一件危险的事情,你应该确定你正确地做到了; 让你拼出演员要求注意你可能会失去精确度或幅度.
其次,双打和小数的用法非常不同.双打通常用于科学计算,其中1.000000000001和0.99999999999之间的差异远小于实验误差.产生小的表示错误是无关紧要的.小数通常用于精确的财务计算,需要对便士完全准确.偶然混合两者似乎很危险.
有时你必须这样做; 例如,更容易找出"指数"问题,如抵押摊还或复合利息双倍应计.在这些情况下,我们再次说明您要从双精度转换为十进制,以便明确表示这是程序中的一个点,如果您没有正确的话,可能会发生精度或幅度损失.
为什么将双字面值转换为十进制字面值是非法的?为什么不假装它是十进制字面值?
C#不是"为你隐瞒你的错误"的一种语言.它是"告诉你你的错误,所以你可以解决它们"这种语言.如果你想说"2.3m"而你忘了"m"那么编译器应该告诉你它.
那么为什么将整数文字(或任何整数常量)转换为short,byte等是合法的呢?
因为可以检查整数常量以查看它是否在编译时处于正确的范围内.从范围内整数到较小整数类型的转换始终是精确的; 与双/十进制转换不同,它永远不会丢失精度或幅度.此外,整数常量算术总是在"已检查"的上下文中完成,除非您使用未经检查的块覆盖它,因此甚至没有溢出的危险.
并且整数/短算术不太可能跨越"域"边界,如双/十进制算术.双算术很可能是科学的,十进制算术可能是经济的.但整数和短算术并不明确地与不同的业务领域相关联.
使其合法意味着您不必编写将常量强制转换为正确类型的丑陋不必要的代码.
因此,没有充分的理由使其成为非法的,并且有充分理由使其合法化.
Jon*_*eet 11
这里有一些事情:
double文字转换为float隐式文字.那不行.double为decimal(这是允许的,但通常不是一个好主意),然后隐式转换decimal为float(这是不允许的).如果x是指被声明为decimal,那么唯一需要的转换是double到decimal-这还不是一个好主意,通常.整数文字的工作转换是由于"隐式常量表达式转换",如C#4规范的6.1.9节所述:
甲常数表达式类型的
int可转换为类型sbyte,byte,short,ushort,uint或ulong,所提供的值常数表达式是在目标类型的范围内.
有类似的东西long,但不为double.
基本上,当您编写浮点常量时,最好使用后缀显式指定类型:
double d = 2.3d;
float f = 2.3f;
decimal m = 2.3m;
Run Code Online (Sandbox Code Playgroud)