1)如果一个操作数的类型为ulong
,而另一个操作数的类型为sbyte/short/int/long
,则会发生编译时错误。我没有看到这个逻辑。因此,为什么两个操作数都被提升为double
或float
类型,这是不错的主意?
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
字面值转换为byte
类型,并将结果值分配给b
:
byte b = 1;
但是如果我们尝试将ulong
类型的文字分配给long
类型(或类型int
,byte
等),那么编译器会报告错误:< / p>
long L = 1000UL;
我认为编译器能够弄清楚常量表达式的结果是否适合long
类型的变量?!
谢谢
答案 0 :(得分:8)
要回答标记为(1)的问题 - 添加已签名和未签名的长片可能是错误。如果开发人员的意图是在这个场景中溢出到不精确算术中,那么他们应该通过将两个参数都转换为double来明确地做。隐含地这样做是隐藏错误比做正确的事情更频繁。
回答标记为(b)的问题 - 当然编译器可以解决这个问题。显然它可以因为它对整数文字这样做。但同样,这几乎肯定是一个错误。如果您的意图是签名长,那么为什么将其标记为未签名?这看起来像错误。 C#经过精心设计,因此它会寻找像这样的奇怪模式并引起你的注意,而不是猜测你是想说出这个奇怪的东西并且在前方炽热,好像一切正常。编译器试图鼓励你编写合理的代码; 明智的代码不会混合有符号和无符号类型。
答案 1 :(得分:2)
为什么要这样?
通常,这两种类型是不兼容的,因为long是签名的。您只描述了一个特例。
对于byte b = 1;
1,没有隐式类型,可以强制转换为字节
对于long L = 1000UL;
“1000UL” 具有明确类型且不兼容,请参阅上面的一般情况。
来自"ulong" on MSDN的示例:
当整数文字没有后缀时, 它的类型是这些类型中的第一种 其值可以表示为: int,uint,long,ulong。
然后
没有隐式转换 ulong到任何整数类型
MSDN中的“long”(我的粗体)
当整数文字没有后缀时, 它的类型是这些类型的第一 其值可以表示为: int,uint,long,ulong。
这是非常普遍和合乎逻辑的,完全可预测的
答案 2 :(得分:2)
long l = 100;
ulong ul = 1000;
double d = l + ul; // error
为什么两个操作数都被提升为double或float类型?
哪一个?花车?或者双打?或者小数点?还是多头?编译器无法知道你在想什么。此外,类型信息通常不会从表达式中流出,因此它不能使用赋值的目标来选择。
修复方法是通过将一个或两个参数强制转换为该类型来简单地指定所需的类型。
答案 3 :(得分:2)
在确定表达式的结果类型时,编译器不会考虑对结果执行的操作。如何在表达式中提升类型的规则仅考虑表达式本身的值,而不考虑稍后对值的处理。
如果您将结果分配给变量,则可以使用该信息,但请考虑如下语句:
Console.Write(L + UL);
Write
方法具有多种不同数据类型的重载,这使得决定如何使用该信息变得相当复杂。
例如,有一个带有字符串的重载,所以一种可能的方法来提升类型(以及一个好的候选者,因为它不会丢失任何精度)将首先将两个值转换为字符串然后连接它们,这可能不是你追求的结果。
答案 4 :(得分:1)
简单的答案就是语言规范的编写方式:
http://msdn.microsoft.com/en-us/library/y5b434w4(v=VS.80).aspx
你可以争论隐含转换的规则在每种情况下是否合乎逻辑,但在一天结束时这些只是设计委员会决定的规则。
任何隐式转换都有缺点,因为它正在做程序员可能没想到的事情。 c#的一般原理似乎是在这些情况下出错,而不是试着猜测程序员的意思。
答案 5 :(得分:0)
假设一个变量等于9223372036854775807而另一个变量等于-9223372036854775806?添加的结果应该是什么?将这两个值转换为double
会将它们分别舍入为9223372036854775808和-9223372036854775808;然后执行减法将产生0.0(确切地)。相反,如果两个值都已签名,则结果为1.0(也是精确的)。可以将两个操作数转换为类型Decimal
并完全进行数学运算。但是,在事实之后转换为Double
需要显式转换。