为什么将NaN转换为长期产生有效结果?

bra*_*mus 21 c#

在下面的示例代码中,我除以零,当我使用调试器逐步执行时,(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关键字使其成为炸弹.