为什么在以下情况下会出现算术溢出:(Int64)(System.Data.SqlTypes.SqlInt16.MaxValue + 1);

时间:2014-02-20 09:46:58

标签: c# .net overflow int64

我在下面的表达中忽略了什么? 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 Overflow

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

到Int64?

(它与C#中的+运算符的实现有关吗?或者??)

5 个答案:

答案 0 :(得分:3)

SqlTypes.SqlInt16是一个有趣的类型。 看起来像 short? 但它不是,它实际上是 struct 。它有一堆运算符重载,使其行为像一个数字。请注意这个版本如何工作正常:

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

使用"正常"加法运算符,它永远不会溢出,因为CLR实际上没有一个适用于 short 的加法运算符。它支持的最近类型是Int32,这里不会溢出。

但是编写SqlInt16是为了捕获这个错误,它有一个operator+()重载,它被明确写入以生成此异常。换句话说, 实现16位加法的语义,并在结果不适合16位整数类型的dbase表列时大喊。无论您是否在C#中使用已检查未经检查的关键字。这是一件好事,当你使用dbase时,你真的想知道这一点。

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

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

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

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

请注意像这样的代码的iffy语义。您无法投射dbase列。我的第一个片段更有意义。

答案 1 :(得分:2)

您正尝试将结果SqlInt16.MaxValue+1投射到Int64。但SqlInt16.MaxValueSqlInt16。在你施放它之前,为它添加+1将会溢出。


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

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

答案 2 :(得分:1)

请执行此操作,尝试将System.Data.SqlTypes.SqlInt16

的最大值加1
Int64 value = (Int64)(System.Data.SqlTypes.SqlInt16.MaxValue) +1;

答案 3 :(得分:1)

因为(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

答案 4 :(得分:0)

将鼠标悬停在代码中的+符号上,然后会弹出一个工具提示,告诉您(重载分辨率)转到“用户定义”操作符。在+字符上选择“转到定义”或F12,您将看到签名:

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

documentation

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

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

要解决此问题,请明确将System.Data.SqlTypes.SqlInt16.MaxValue转换为例如Int64(又名long)或Int16(又名short 之前 添加(+ )。

当然,您也可以使用:

long value = short.MaxValue + 1;

因为short.MaxValueSqlInt16.MaxValue具有相同的数值,但我不知道您是否可以在应用程序中使用它。