在将Int64转换为Int32时,为什么C#让我溢出而没有任何错误或警告?它是如何进行转换的?

Nib*_*Pig 7 c#

这个问题源于一个错误,我迭代了一个集合,Int64并意外地做了foreach (int i in myCollection).我试图调试令人困惑的问题,当我做一个linq查询,i不是一部分myCollection.

这里有一些令我惊讶的代码:

Int64 a = 12345678912345;

Console.Write((int)a);
Run Code Online (Sandbox Code Playgroud)

我希望编译器给我一个错误.通常的一个是隐式演员表不存在.但不,它根本不介意这一点.甚至没有警告!

(int)a偶然的输出值是1942903641.

我很想知道为什么演员在没有任何警告的情况下被允许,以及它是如何产生这个价值的.有任何想法吗?

Han*_*ant 14

默认情况下,不会检查此类转换.你必须明确地要求它:

   Console.Write(checked((int)a));    // Kaboom!
Run Code Online (Sandbox Code Playgroud)

可以通过C#编译器的/ checked选项全局启用已检查的转换.项目模板没有为Debug构建启用此选项是我书中的疏忽,溢出可能非常难以诊断.

但是,您无法解决任何问题,只需使用项目>属性>构建选项卡>高级按钮>勾选"检查算术溢出/下溢"选项.并注意你的foreach循环现在如何使用OverflowException进行轰炸.请记住,当它发生时你会盯着它看几分钟:)这不是一个非常便宜的检查,所以你会想要将它留给Release版本.


Tim*_* S. 6

默认情况下,C#在处理数字时不检查溢出.这包括诸如从包装int.MaxValueint.MinValue在加法和乘法,而当你施放longs到int秒.要控制它,请使用checkeduncheckedkeywords/checked编译器选项.

该值1942903641long截断为a 时的结果int.它来自该long值的32个最低有效位,作为二进制补码有符号整数.

使用时foreach,重要的是要知道如果声明的类型与枚举的类型不匹配,它会将其视为您转换为该类型.foreach (int i in myCollection)编译成类似的东西int i = (int)myEnumerator.Current;,而不是int i = myEnumerator.Current;.您可以使用foreach (var i in myCollection)以避免将来出现此类错误.var 建议用于循环变量forforeach语句.

您可以在以下示例中看到各种事物的结果(十六进制输出用于更清楚地显示截断:它们具有相同的结束数字,int只是缺少一些更有效的数字):

checked
{
    Int64 a = 12345678912345;
    Console.WriteLine(a.ToString("X"));
    Console.WriteLine((a % ((long)uint.MaxValue + 1L)).ToString("X"));
    try
    {
        Console.WriteLine(((int)a).ToString("X")); // throws exception
    }
    catch (Exception e)
    {
        Console.WriteLine("It threw! " + e.Message);
    }
}
unchecked
{
    Int64 a = 12345678912345;
    Console.WriteLine(a.ToString("X"));
    Console.WriteLine((a % (long)Math.Pow(2, 32)).ToString("X"));
    Console.WriteLine(((int)a).ToString("X"));
}
Run Code Online (Sandbox Code Playgroud)

这输出:

B3A73CE5B59
73CE5B59
It threw! Arithmetic operation resulted in an overflow.
B3A73CE5B59
73CE5B59
73CE5B59
Run Code Online (Sandbox Code Playgroud)

  • @SLC可能出于营销原因.请参阅[默认情况下为什么语言不会引起整数溢出错误?](http://stackoverflow.com/questions/103654/why-dont-languages-raise-errors-on-integer-overflow-by-default) (2认同)