为什么 int32.maxvalue + 1 会导致 long 溢出?

8
如果您将以下代码放入.NET 4.5应用程序中:
public const long MAXIMUM_RANGE_MAGNITUDE = int.MaxValue + 1;

生成编译器错误,指出“在检查模式下,在编译时发生溢出操作”。我知道我可以将此放入“未经检查的”块中并且没有问题,但我的问题是为什么首先会出现错误?显然,long可以容纳int的最大值加一。
请注意,使用Int32和Int64而不是long和int似乎没有帮助。

13
它不会溢出 long 类型;它会溢出 int 类型。 - Michael Liu
当运行时评估此内容时,它会取一个32位整数并将其加1。 - Matan Shahar
这样做的唯一方法是以未经检查的模式进行吗? - BradleyDotNET
5个回答

20
右侧赋值运算的计算是以整数类型进行的,这就导致了整数溢出。您可以通过以下方式修复:
public const long MAXIMUM_RANGE_MAGNITUDE = int.MaxValue + (long)1; // or 1L

通过将至少一个操作数转换为long
您之所以会出现错误,是因为在C#规范中指定了原因。
请参见C#规范第4.1.5节(整数类型) 对于二进制+、-、*、/、%、&、^、|、==、!=、>、<、>=和<=运算符,操作数转换为类型T,其中T是int、uint、long和ulong中能够完全表示两个操作数的所有可能值的第一个类型。然后使用类型T的精度执行操作,并且结果的类型为T(或关系运算符的布尔类型)。不允许一个操作数为long类型,另一个操作数为ulong类型的二进制运算符。
在您的情况下,由于加法的两个操作数都可以用int表示,因此计算是在整数类型中完成的。将其中一个操作数显式转换为long将导致long结果,从而没有溢出错误。

2
太棒了,谢谢你的答案。我尝试了一些不同的代码变化,但显然没有找到正确的解决方法!然而,你的代码运行得非常好。 - BradleyDotNET

4

你的代码实际上长这样:

(long)(int.MaxValue + 1)

但是因为.Net框架内置了int和long之间的隐式转换,所以您不需要在代码中显式地进行long类型的强制转换。
所以首先执行代码的这一部分:
int.MaxValue + 1

这个操作的结果是一个int值,会导致溢出异常。因此你的代码甚至没有机会将int转换为long。


1
尝试
public const long MAXIMUM_RANGE_MAGNITUDE = (long)int.MaxValue + 1L;

1
将常量值强制转换为长整型。
public const long MAXIMUM_RANGE_MAGNITUDE = (long) int.MaxValue + 1;

1
我认为这与计算int.MaxValue + 1的值在转换为long之前有关。虽然long可以容纳该值,但由于进行整数加法,因此在转换之前无法将int.MaxValue + 1的整数值存储在一个int中。请保留html标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接