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

C# 不同类型的溢出检查行为不一致,c#,int,double,decimal,long-integer,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(decim

我有一段有趣的代码:

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
会引发
溢出异常
,即使我已明确指定
未选中

编辑:有趣。表示以下操作受溢出检查的影响:

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

这里的关键字是intergal。让我们看看:

sbyte字节字符短ushort int uint长ulong

因此,
decimal
的行为与
int
不同是有道理的,但是
double
是怎么回事?

首先注意:


  • 未选中
    完全不影响十进制和双精度
  • 所有这些都不依赖于动态
  • 双人间怎么了

    引用C规范:

    •对于从浮点型或双精度型到整数型的转换,处理取决于发生转换的溢出检查上下文(§7.6.12):

    o在未检查的上下文中,转换始终成功,并按如下方式进行

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

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

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

    因此,结果不详

    十进制:

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

    这是在这里观察到的


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

    十进制与其他浮点数对象在二进制数的准确性和存储方面有所不同。详细解释。
    未选中
    完全不影响十进制和双精度。这是标准行为。此外,所有这些都不依赖于动态。为了清晰起见,我建议将其移除。