在下面的示例代码中,我除以零,当我使用调试器逐步执行时,(dividend/divisor)产生无穷大或NaN(如果除数为零).当我将此结果转换为长时间时,我得到一个有效的结果,通常类似于-9223372036854775808.为什么这个演员有效?为什么不停止执行(例如抛出异常)而不是分配任意值?
double divisor = 0;
double dividend = 7;
long result = (long)(dividend / divisor);
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 24
为什么这个演员有效?
如果在编译时已知转换可能成功或始终成功,则强制转换有效.只有在转换无法成功时,转换才是非法的.(例如,将密封类型转换为未实现的接口.)从double到long的转换可能会成功.因此演员表是有效的.
为什么不停止执行(例如抛出异常)而不是分配任意值?
因为你没有要求例外!该规范非常清楚预期的行为是什么.见6.2.1节:
对于从float或double到整数类型的转换,处理取决于发生转换的溢出检查上下文:
在已检查的上下文中,转换过程如下:
•如果操作数的值为NaN或无穷大,则抛出System.OverflowException.
[...]
在未经检查的上下文中,转换始终成功,并按如下方式进行.
•如果操作数的值为NaN或无穷大,则转换结果为目标类型的未指定值.
您正在未经检查的上下文中执行代码; 你没有要求任何例外,所以你没有例外.如果你想要一个例外,请求一个; 使用检查的上下文.
SLa*_*aks 14
默认情况下,未选中C#算术,因此无效操作不会抛出异常.
您可以使用checked块来强制运行时检查溢出并抛出异常,如下所示:
checked {
double divisor = 0;
double dividend = 7;
long result = (long)(dividend / divisor);
}
Run Code Online (Sandbox Code Playgroud)
请注意,会有轻微的性能损失.
Han*_*ant 11
该行为在C#语言规范第6.2.1节中明确记录:
对于从float或double到整数类型的转换,处理取决于转换发生的溢出检查上下文(第7.5.12节):
在已检查的上下文中,转换过程如下:
- 如果操作数的值为NaN或无穷大,则抛出System.OverflowException.
- 否则,源操作数向零舍入为最接近的整数值.如果此整数值在目标类型的范围内,则此值是转换的结果.
- 否则,抛出System.OverflowException.
在未经检查的上下文中,转换始终成功,并按如下方式进行.
- 如果操作数的值为NaN或无穷大,则转换的结果是目标类型的未指定值.
- 否则,源操作数向零舍入为最接近的整数值.如果此整数值在目标类型的范围内,则此值是转换的结果.
- 否则,转换的结果是目标类型的未指定值.
大胆增加强调.你有Infinity和一个未经检查的上下文.你得到的价值是未指定的.使用checked关键字使其成为炸弹.