我实际上是在未经检查的上下文中测试C#中的转换行为。就像文档中所说的那样,在未经检查的上下文中,强制转换总是成功的。但是有时,在特定情况下,从一种特定类型到另一种类型的转换会产生意外的结果。
例如,我测试了三个“ double to sbyte”转换:
var firstCast = (sbyte) -129.83297462979882752; // Result : 127.
var secondCast = (sbyte) -65324678217.74282742874973267; // Result : 0.
var thirdCast = (sbyte) -65324678216.74282742874973267; // Result : 0.
请注意,第二个和第三个两倍之间的差仅为1
(secondDouble - firstDouble = 1
)。在这种情况下,对于任何“大”双精度值,强制转换的结果似乎始终为0
。
我的问题是:为什么第二次和第三次强制转换会导致0
?我在C#文档中搜索了答案,但没有找到任何答案。
我使用.Net Framework 4.7.2测试了以上内容。
对于从float或double到整数类型的转换,处理取决于发生转换的溢出检查上下文:
[不使用checked
或unchecked
运算符,默认情况下,不检查溢出检查上下文,因此我们来看:
在未检查的上下文中,转换总是成功,并且按如下进行。
如果操作数的值为NaN或无穷大,则转换结果为目标类型的未指定值。
否则,源操作数朝零舍入到最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。
否则,转换结果是目标类型的未指定值。
这里,值既不是NaN也不是无穷大。朝零取整时,它们不在sbyte
的有效范围内,该范围为-128到127,因此最后一个项目符号点适用,这意味着这种转换的结果未指定。
换句话说,此强制转换的结果取决于您使用的编译器。不同的编译器可以做不同的事情,它们仍将被称为C#编译器。无论您使用的编译器是什么,都可能以为要转换的值离下/上限很远时,返回0进行转换是一个更好的主意。