【问题标题】:Why do I get Arithmetic overflow when :(Int64)(System.Data.SqlTypes.SqlInt16.MaxValue+1);为什么在 :(Int64)(System.Data.SqlTypes.SqlInt16.MaxValue+1); 时出现算术溢出
【发布时间】:2014-02-20 09:46:57
【问题描述】:

我在下面的表达式中忽略了什么? Int64 类型的范围不是比 Int16 大吗?

Int64 value = (Int64)(System.Data.SqlTypes.SqlInt16.MaxValue+1);

System.Data.SqlTypes.SqlInt16.MaxValue 为 32767。 Int64.MaxValue() 为 9223372036854775807。

32767 + 1 = 32768。这比 9223372036854775807 低很多(!)。

那么为什么我在施放时会得到 Aritmethic 溢出

(Int64)(System.Data.SqlTypes.SqlInt16.MaxValue+1);

到 Int64?

(是和C#中+运算符的实现有关还是...?)

【问题讨论】:

    标签: c# .net overflow int64


    【解决方案1】:

    SqlTypes.SqlInt16 是一个有趣的类型。它看起来像一个short?,但其实不是,它实际上是一个struct。它有一堆运算符重载,使其表现得像一个数字。请注意此版本的工作原理:

        Int64 value = (Int64)(short.MaxValue + 1);    // okay
    

    它使用“普通”加法运算符,它永远不会溢出,因为 CLR 实际上没有适用于 short 的加法运算符。它支持的最接近的类型是 Int32,这里不会溢出。

    但是 SqlInt16 是为了捕捉这个错误而编写的,它有一个 operator+() 重载,它被显式编写来生成这个异常。换句话说,它确实实现了 16 位加法的语义,并在结果不适合 16 位整数类型的 dbase 表列时大喊大叫。无论您在 C# 中使用 checked 还是 unchecked 关键字。这是一件好事,当您使用 dbase 时,您真的很想知道这一点。

    您需要调用另一个SqlInt16 方法,一个conversion 运算符。将 SqlInt16 转换为本机整数类型的一种。诙谐的版本如下所示:

       Int64 value = (Int64)((short)System.Data.SqlTypes.SqlInt16.MaxValue + 1);
    

    当然,直接转换为 Int64 更有意义,SqlInt16 也有一个转换运算符:

       Int64 value = (Int64)System.Data.SqlTypes.SqlInt16.MaxValue + 1;
    

    请注意此类代码的不确定语义。您不能转换 dbase 列。我的第一个 sn-p 更有意义。

    【讨论】:

      【解决方案2】:

      您正试图将SqlInt16.MaxValue+1 的结果转换为Int64。但是SqlInt16.MaxValueSqlInt16。添加 +1 会在你施放之前溢出。


      您要做的是首先将SqlInt16.MaxValue 转换为Int64,然后将1 添加到其中:

      Int64 value = (Int64)System.Data.SqlTypes.SqlInt16.MaxValue + 1;
      

      【讨论】:

        【解决方案3】:

        改为执行此操作,您尝试将 System.Data.SqlTypes.SqlInt16 的最大值加 1

        Int64 value = (Int64)(System.Data.SqlTypes.SqlInt16.MaxValue) +1;
        

        【讨论】:

          【解决方案4】:

          因为(System.Data.SqlTypes.SqlInt16.MaxValue+1)int16 - 或尝试 至少是无效的。

          只需先将MaxValue 转换为int64,然后再加1。

          只是为了举例说明:

          var x = (System.Data.SqlTypes.SqlInt16.MaxValue + 0);
          var t = x.GetType(); // t will be System.Data.SqlTypes.SqlInt16
          

          【讨论】:

            【解决方案5】:

            将鼠标悬停在代码中的+ 符号上,您会弹出一个工具提示,告诉您它(重载解决方案)转到“用户定义”运算符。在+ 字符上选择“转到定义”或 F12,您将看到签名:

            public static SqlInt16 operator +(SqlInt16 x, SqlInt16 y);
            

            (documentation)

            所以您现在知道右侧操作数 1 被隐式转换为 SqlInt16(首先通过 C# 的常量(文字)表达式转换规则从 int 隐式转换为 short,然后从 @ 转换987654329@ 到 SqlInt16 通过“用户定义”implicit operator)。然后我们有两个SqlInt16 值。上面的operator 将它们带入并希望返回第三个SqlInt16 值,即它们的总和。但这是不可能的。出现异常。

            所以我们永远不会把你的演员表联系到Int64;问题发生在此之前。

            要修复它,请将System.Data.SqlTypes.SqlInt16.MaxValue 显式转换为例如Int64(又名long)或Int16(又名short之前添加(+)。

            当然,你也可以使用:

            long value = short.MaxValue + 1;
            

            因为short.MaxValueSqlInt16.MaxValue的数值是一样的,但是不知道你的应用能不能用这个。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-01
              • 2011-12-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多