而不是错误,为什么两个操作数都不会被提升为float或double?

1)如果一个操作数是ulong类型,而另一个操作数是sbyte/short/int/long ,则发生编译时错误。 我没有看到这个逻辑。 因此,为什么两个操作数被提升为doublefloat类型会是个坏主意呢?

  long L = 100; ulong UL = 1000; double d = L + UL; // error saying + operator can't be applied to operands of type ulong and long 

b)编译器隐式地将int literal转换为byte类型并将结果值赋给b

 byte b = 1; 

但是如果我们尝试为long类型(或类型intbyte等)分配ulong类型的文字,那么编译器会报告错误:

 long L = 1000UL; 

我认为编译器能够弄清楚常量表达式的结果是否适合long类型的变量?!

谢谢

要回答标记为(1)的问题 – 添加有符号和无符号长度可能是一个错误 。 如果开发人员的意图是在这种情况下溢出到不精确的算术,那么他们应该通过将两个参数都转换为double来明确地做。 隐含地这样做是为了更多地隐藏错误而不是做正确的事情

回答标记为(b)的问题 – 当然编译器可以解决这个问题。 显然它可以因为它对整数文字这样做。 但同样,这几乎肯定是一个错误。 如果你的意图是签名长,那你为什么把它标记为未签名 ? 这看起来像是一个错误 。 C#经过精心设计,因此它会寻找像这样的奇怪模式并引起你对它们的注意,而不是猜测你是想说出这个奇怪的东西并且开始前进,好像一切正​​常。 编译器试图鼓励你编写合理的代码; 敏感代码不会混合有符号和无符号类型

为什么要这样?

通常,这两种类型是不兼容的,因为long是签名的。 您只描述了一个特例。

对于byte b = 1; 1本身没有隐式类型,可以强制转换为字节

long L = 1000UL; “1000UL” 确实有一个明确的类型,并且是不兼容的,请参阅上面的一般情况。

MSDN上“ulong”的示例:

当整数文字没有后缀时,它的类型是这些类型中的第一个,其值可以表示为:int,uint,long,ulong。

然后

没有从ulong到任何整数类型的隐式转换

在MSDN中的“长”(我的粗体)

当整数文字没有后缀时,它的类型是这些类型中的第一个 ,其值可以表示为:int,uint,long,ulong。

它非常普遍,合乎逻辑,完全可以预测

 long l = 100; ulong ul = 1000; double d = l + ul; // error 

为什么两个操作数被提升为double或float类型会是个坏主意?

哪一个? 花车? 还是双打? 或者小数点? 还是多头? 编译器无法知道你在想什么。 此外,类型信息通常不会从表达式中流出,因此它不能使用赋值的目标来选择。

修复方法是通过将一个或两个参数转换为该类型来简单地指定所需的类型。

在确定表达式的结果类型时,编译器不会考虑对结果执行的操作。 如何在表达式中提升类型的规则仅考虑表达式本身的值,而不考虑稍后对值的处理。

在将结果分配给变量的情况下,可以使用该信息,但请考虑如下语句:

 Console.Write(L + UL); 

Write方法具有多个不同数据类型的重载,这使得决定如何使用该信息变得相当复杂。

例如,有一个带有字符串的重载,因此一种可能的方法来提升类型(以及一个好的候选者,因为它不会失去任何精度)将首先将两个值转换为字符串然后连接它们,这是可能不是你追求的结果。

简单的答案就是语言规范的编写方式:

http://msdn.microsoft.com/en-us/library/y5b434w4(v=VS.80).aspx

您可以争论隐式转换的规则在每种情况下是否合乎逻辑,但在一天结束时这些只是设计委员会决定的规则。

任何隐式转换都有一个缺点,就是它正在做程序员可能没想到的事情。 在这些情况下,使用c#的一般主体似乎是错误的,而不是试图猜测程序员的意思。

假设一个变量等于9223372036854775807而另一个变量等于-9223372036854775806? 添加的结果应该是什么? 将这两个值转换为double将分别将它们舍入为9223372036854775808和-9223372036854775808; 然后执行减法将产生0.0(确切地)。 相反,如果两个值都已签名,则结果为1.0(也是精确的)。 可以将两个操作数转换为Decimal类型并完全进行数学运算。 但是,在事实之后转换为Double需要显式转换。