为什么编译器决定2.3是double而不是decimal?

为什么编译器决定2.3是double,所以这段代码不能编译:

decimal x; x = 2.3; // Compilation error - can not convert double to decimal. x = (decimal) 2.3 // Ok 

为什么编译器不这样想:
他想得到一个小数,他给我一个可以是小数的值,所以它是小数!

为什么这不会出现编译错误:

 short x; x = 23; // OK 

谁说23不是int?

这里有很多问题。 让我们把它们分解成小问题。

为什么文字2.3的类型是double而不是decimal?

历史原因。 C#被设计为“类C语法”系列语言的成员,因此其表面外观和基本习语对于使用类C语言的程序员来说是熟悉的。 在几乎所有这些语言中,浮点文字被视为二进制而不是十进制浮点数,因为这就是C最初的做法。

如果我从零开始设计一种新语言,我可能会使模糊的文字变得非法; 每个浮点字面值都必须是非单值,单值或小数,依此类推。

为什么在double和decimal之间隐式转换一般是非法的?

因为这样做可能是一个错误,有两种方式。

首先,双精度和小数具有不同的范围和不同数量的“表示错误” – 也就是说,您希望表示的精确数学量实际表示的数量有多么不同。 将双精度转换为十进制或反之亦然是一件危险的事情,你应该确保你正确地做到了; 让你拼出演员要求注意你可能会失去精确度或幅度。

其次,双打和小数的用法非常不同。 双打通常用于科学计算,其中1.000000000001和0.99999999999之间的差异远小于实验误差。 产生小的表示错误是无关紧要的。 小数通常用于精确的财务计算,需要对便士完全准确。 偶然混合两者似乎很危险。

有时你必须这样做; 例如,更容易找出“指数”问题,如抵押摊还或复合利息双倍应计。 在这些情况下,我们再次说明你要从双精度转换为十进制,以便明确表示这是程序中的一个点,如果你没有正确的话可能会发生精度或幅度损失。

为什么将双字面值转换为十进制字面值是非法的? 为什么不假装它是十进制字面值?

C#不是“为你隐瞒你的错误”的一种语言。 它是“告诉你你的错误,所以你可以解决它们”这种语言。 如果你想说“2.3m”并忘记了“m”那么编译器应该告诉你它。

那么为什么将整数文字(或任何整数常量)转换为short,byte等是合法的呢?

因为可以检查整数常量以查看它是否在编译时处于正确的范围内。 从范围内整数到较小整数类型的转换始终是精确的; 与双/十进制转换不同,它永远不会丢失精度或幅度。 此外,整数常量算术总是在“已检查”的上下文中完成,除非您使用未经检查的块覆盖它,因此甚至没有溢出的危险。

并且整数/短运算不太可能跨越像“双重/十进制算术”这样的“域”边界。 双重算术很可能是科学的,十进制算术可能是经济的。 但整数和短算术并不明确地与不同的业务领域相关联。

并使其合法意味着您不必编写丑陋的不必要的代码,将常量强制转换为正确的类型。

因此,没有充分的理由使其成为非法的,并且有充分理由使其合法化。

这里有一些事情:

  • 在第一个示例中,您尝试隐式地将double字符转换为float 。 那不行。
  • 所谓的工作线实际上是在尝试执行doubledecimal的显式转换(这是允许的,但通常不是一个好主意),然后是decimalfloat的隐式转换(这是不允许的)。 如果x意味着声明为decimal ,那么唯一需要的转换是从doubledecimal – 这通常不是一个好主意。
  • 整数文字的工作转换是由于“隐式常量表达式转换”,如C#4规范的6.1.9节所述:

    如果constant-expression的值在目标类型的范围内,则int类型的常量表达式可以转换为sbytebyteshortushortuintulong类型。

    long有类似的东西,但不是 double

基本上,当您编写浮点常量时,最好使用后缀显式指定类型:

 double d = 2.3d; float f = 2.3f; decimal m = 2.3m; 

2.3 double 。 这是语言规则; 任何带小数点的数字文字都是double ,除非它有F后缀( float )或M后缀( decimal ):

 x = 2.3F; // fine 

编译器也有用地告诉我这个:

double类型的文字不能隐式转换为’float’类型; 使用’F’后缀来创建此类型的文字

因为Floatingpint数字在计算和Valuerange中总是有点困难,所以它们在Immediate符号中始终是最大可能的类型。 (在你的情况下:双倍)。

非浮点在下面有一些相同的处理,因此可以毫无问题地进行转换。 如果您的值超出变量的Value-Range,则可能会导致错误(例如,字节为257)。