不同类型的溢出检查行为不一致

时间:2015-12-05 14:59:46

标签: c# int double decimal long-integer

我有这段有趣的代码:

private static int ConvertToInt(dynamic value)
{
    unchecked
    {
        return (int)value;
    }
}

Console.WriteLine(ConvertToInt(long.MaxValue));
Console.WriteLine(ConvertToInt(double.MaxValue));
Console.WriteLine(ConvertToInt(decimal.MaxValue));

输出:

-1
-2147483648
System.OverflowException: Value was either too large or too small for an Int32.

我发现这有点奇怪。即使我明确指定decimal,为什么从int转换为OverflowException会引发unchecked

编辑:有趣。 MSDN page on checked/unchecked context表示溢出检查会影响以下操作:

  

整数类型之间的显式数字转换。

此处的关键字是 intergal 。我们来看看what types are considered intergal

  

sbyte byte char short ushort int uint long ulong

因此,decimal的行为与int的行为不同,但double的行为是什么呢?

1 个答案:

答案 0 :(得分:0)

首先请注意:

  1. unchecked不会影响小数和双重
  2. 这一切都不依赖于动态
  3.   

    怎么了双重

    引用C#规范:

      

    •对于从float或double到整数类型的转换,处理取决于转换发生的溢出检查上下文(第7.6.12节):

         

    o在未经检查的上下文中,转换始终成功,并按以下步骤继续。

         

    •如果操作数的值为NaN或无穷大,则转换结果是目标类型的未指定值。

         

    •否则,源操作数向零舍入为最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。

         

    否则,转化结果是目的地类型的未指定值。

    所以结果没有说明。

    十进制案例:

      

    •对于从十进制到整数类型的转换,源值将向零舍入到最接近的整数值,并且此整数值将成为转换的结果。如果生成的整数值超出目标类型的范围,则抛出System.OverflowException。

    这里观察到了。

    这个问题很有意思且有效,但是如果你不得不问这是一个代码味道的情况。除非在特殊情况下,否则不要依赖奇怪的转换。问题中提到的所有三个转换都不应该出现在真实世界的代码中,而且我建议编译checked,除非有理由不这样做。通常,大多数时间不是花在应用程序代码上,而是花在其他代码中(例如库或对后端系统的调用)。在这些情况下,checked的性能损失并不明显。