C#浮点字面量:为什么编译器不默认使用左侧变量类型?

6
为了声明浮点数,我们需要在浮点数后面加上“f”表示float类型,加上“d”表示double类型。
例如:
float num1 = 1.23f;   // float stored as float

float num2 = 1.23;    // double stored as float. The code won't compile in C#.

据说如果省略浮点文字,C# 默认为 double 类型。
我的问题是,现代语言“C#”为什么不默认为左侧变量类型呢?毕竟,编译器可以看到整行代码。
这是由于编译器设计的历史原因吗?还是我没有理解到什么地方?

2
除了编译器编写者没有实现它之外,没有任何阻止它的东西。 - Mike Zboray
3
换句话说,除了语言的限制之外没有别的阻碍。问题是为什么会有这种限制。 - juanchopanza
2
@RitchMelton 这并不是一个糟糕的问题。我永远不会因为希望C#编译器更愿意(准确地)预测他们想要什么而责怪任何人。但是,在没有这种能力的情况下,我个人认为他们为什么决定将1.23作为“double”字面量而不是“float”字面量是相当清楚的。 - furkle
3
如果你明确提供了要分配 lvalue 的类型,那么当自动转换时是可以的。但 var 呢?如果允许 float f = 1.0,但是 var d = 1.0 的类型是 double,这样不会变得有点奇怪吗?对我来说,这似乎是为了能够使用隐式类型而做出的一种牺牲。 - furkle
@furkle 你觉得 float i = 1var i = 1int 这个现象很奇怪吗? - Mike Zboray
显示剩余8条评论
3个回答

7

我认为主要原因是可预测性和一致性。

假设你是编译器,你需要确定以下语句中字面量3.14的类型:


float p = 3.14;

第一个很简单,显然应该是浮点数。
那么这个呢?
var x = 3.14 * 10.0f;

用户在10.0之后明确添加了,所以应该是浮点数,那3.14呢?x应该是 double 还是 float

还有这一个:

bool b = 3.14 / 3.14f == 1;

第一个 3.14double 还是 float?变量 b 的值取决于它!


作为用户,我更愿意明确添加一个 f 并且确切地知道我得到了什么。


1
这里可能有其他人能够解释为什么.NET开发人员决定不使用某种预测来确定数字字面量应该如何强制转换为提供给它的类型。但在没有任何哲学基础的情况下,答案很简单:他们不想那样做,所以他们就没做。我不会告诉你你完全不需要关心这个问题,因为当然想让编译器明确了解你想要的东西是不完全不合理的。这至少会让人感觉好些,对吧?
(如果必须猜测的话,我猜这与允许某种逻辑隐式类型有很大关系- float f = 1.0float,但var d=1.0double? 当你考虑到f.Equals(d)将是false,尽管1.0==1.0true时,这变得更不合乎逻辑了。)
但是,假设他们有充分的理由不引入任何类型定义特定的预测(Rotem的帖子中还可以找到一些更好的理由),我能想象的最好的理由是他们决定double num1 = 1.23是可接受的,而float num1 = 1.23则不是,是因为在大多数情况下,double更有用。与使用32位浮点值相比,使用64位浮点值的CPU和IO惩罚在大多数用例中都是可以忽略不计的,但是不必担心超出该数据类型范围的有用性显着。
请注意,您可以对为什么不能将1.23分配给没有后缀的decimal提出完全相同的论据。设计C#的人决定对任何给定格式的数字文字类型进行假设是更容易的,并且假设大多数写1.23的人想要一个double,或者至少应该使用一个。
编辑:用户修正了标题。

1
因为您提出的功能基本上会使编译器不一致。规则简单易懂:3.14double3.14ffloat
您的示例很简单,但您正在看小图像:
float x = 3.14;

好的,假设编译器足够“聪明”以将文本解析为浮点数。

double x = 3.14;

嗯,现在同样的字面值是一个double,而且没有从floatdouble的隐式转换...奇怪。那么下面的类型应该是什么?

var x = 3.14;

同一问题的其他类似变体:

int i = 2 * 3.14;

编译时错误应该是什么?无法将double隐式转换为int或将float转换为int。为什么一个比另一个更好?
var x = 2 * 3.14;

噢,噢,现在怎么办?

C#设计师决定将十进制数字文字解析为double类型...总是这样。如果您想要另一种类型(floatdecimal),则需要明确指定。优点:一致性。他们本来可以决定将float作为隐式类型,但是这样做会使事情变得混乱。

此外,重要的是要注意,C#解析规则(类型、方法等)始终忽略表达式左侧的类型。您的功能将使编译器根据左侧的类型更改其类型解析,这也与语言行为不一致。


每个人都提供了非常有启发性的评论和答案,但我只能接受一个答案。 - 911

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接