当在C#中需要基值类型的强制转换时
本文关键字:转换 类型 当在 | 更新日期: 2023-09-27 18:26:11
当使用数学运算时,我有一个关于在基值类型之间转换的一般问题。微软C#规范中有书面规则吗?我找不到他们。它在Mono中也一样吗?
示例:
double a = 1 / 1234; //Result is 0
double b = 1.0 / 1234; //Result is 0,000810372771474878
double c = 1.0 / (double)1234; //Result is 0,000810372771474878
double d = (double)1 / (double)1234; //Result is 0,000810372771474878
double e = 1 / 1234.0; //Result is 0,000810372771474878
当被除数或除数是双时,我能假设结果总是双吗?或者出于某种原因,最好确保两者都是双重的(见案例d-我见过很多这样的代码,实际上让我问这个问题)
谨致问候,Sebastian
长话短说,是的,当二进制操作的至少一侧被键入时,可以安全地假设编译器将假定double
。你不需要明确(当然,从可读性的角度来看,有时它可能很有用,这并不真正相关,但值得一提)。
需要明确的是,尽管我认为你在最初的问题中没有混淆这一点,但你分配结果的变量类型对除法运算符过载的确定方式没有影响。
您的top case只是使用了一个隐式转换,它将具有与此显式等价的转换。
double a = (double)(1 / 1234);
将其分配给double
的事实不会影响1 / 1234
计算为0
的事实,正如您所发现的那样,因为该强制转换是在除法之后发生的。如果我们在这里的时空中切开一个洞,这个例子将落在这篇文章底部列表的最后一种情况下,其中两个整数被除以。因此,根据规范第7.8.2节,这将返回商的底数或0
。
这种行为在C#5规范的7.3.6节中有描述(我承认,这花了一些时间),重点是我的。
7.3.6数字促销
当重载解析规则(§7.5.3)应用于这组运算符时,其效果是从操作数类型中选择存在隐式转换的第一个运算符。例如,对于操作b*s,其中b是字节,s是短运算符,重载解析选择运算符*(int,int)作为最佳运算符。因此,效果是b和s被转换为int,结果的类型是int。同样,对于运算i*d,其中i是int,d是double,重载解析选择运算符*(double,double)作为最佳运算符
当然,这不仅适用于乘法,正如它的例子所示,也适用于任何二进制运算。
为了更好地衡量,层次结构如下,取自7.3.6.2,重点仍然是我的。
•如果其中一个操作数是十进制类型,则另一个操作数会转换为十进制类型,或者如果另一个运算数是浮点或双精度类型,则会发生绑定时间错误
•否则,如果任一操作数的类型为double,则另一个操作数将转换为double类型
•否则,如果其中一个操作数的类型为float,则另一操作数将转换为float类型
•否则,如果其中一个操作数的类型为ulong,则另一个操作数会转换为ulong类型;如果另一个操作数的类型是sbyte、short、int或long,则会发生绑定时间错误
•否则,如果任一操作数的类型为long,则另一个操作数将转换为long类型
•否则,如果任一操作数的类型为uint,另一个操作数类型为sbyte、short或int,则两个操作数都将转换为long类型
•否则,如果任一操作数的类型为uint,则另一个操作数将转换为uint类型
•否则,两个操作数都转换为int类型。
实际上,编译器通过将非double
操作数转换为类型double
,实际上为您执行了转换。
当您将两个整数进行除法时,会得到一个整数结果。由于int
不能容纳0,000810372771474878
,因此结果将被截断为0
,然后0
(int)被转换为double
,得到0.0
作为结果。
为了获得浮点结果,其中一个操作数应该是浮点类型。在这种情况下,整数操作数将转换为double
/float
或decimal
,具体取决于数字的类型。
C# Specification 7.7.2 Division operator
中有关于除法运算符的详细信息