3

我使用 C# 在 .Net 3.5 中运行了一个程序,效果很好

try
{
    int i = 2147483647;

    Console.WriteLine((i * 100 / i).ToString());

    Console.ReadLine();
}
catch (Exception)
{                
    throw;
}

当我在 C# 中运行这个程序时,我没有收到异常(它输出“0”)。但是当我在 VB.Net 中运行这个程序时,它会导致"Arithmetic operation resulted in an overflow"异常

Try
    Dim i As Integer = 2147483647

    Console.WriteLine((i * 100 / i).ToString())

    Console.ReadLine()
Catch ex As Exception
    Throw
End Try

为什么这两种语言之间的行为不同?

4

3 回答 3

5

也许看看 IL 会澄清......稍微简化你的代码:

C#:

int i = 2147483647;
int v = (i * 100 / i);

生成以下 IL:

IL_0001:  ldc.i4      FF FF FF 7F 
IL_0006:  stloc.0     // i
IL_0007:  ldloc.0     // i
IL_0008:  ldc.i4.s    64 
IL_000A:  mul         
IL_000B:  ldloc.0     // i
IL_000C:  div         
IL_000D:  stloc.1     // v

而VB版本:

Dim i As Integer = 2147483647
Dim v As Integer
v = i * 100 / i

生成此 IL,略有不同:

IL_0001:  ldc.i4      FF FF FF 7F 
IL_0006:  stloc.0     // i
IL_0007:  ldloc.0     // i
IL_0008:  ldc.i4.s    64 
IL_000A:  mul.ovf     
IL_000B:  conv.r8     
IL_000C:  ldloc.0     // i
IL_000D:  conv.r8     
IL_000E:  div         
IL_000F:  call        System.Math.Round
IL_0014:  conv.ovf.i4 
IL_0015:  stloc.1     // v

如您所见,VB 调用mul.ovf的是“乘法并检查溢出”,而 C# 调用mul的是不检查溢出的调用。

也许它不能回答你关于为什么C# 以一种方式和 VB 以另一种方式做的问题,但至少它回答了它为什么会发生。:)

编辑:查看阿奎那的答案以获得“为什么”。

于 2013-07-06T04:20:38.610 回答
1

尝试将您的程序更改为:

try {
    checked {
        int i = 2147483647;
        Console.WriteLine((i * 100 / i).ToString());
        Console.ReadLine();
    }
}
catch (Exception) {
    throw;
}

默认情况下,C# 不会自动执行算术检查。但是,如果您转到项目属性...构建选项卡..高级...“[X] 检查算术上溢/下溢”,那么默认情况下您将获得与 VB.NET 相同的行为。

于 2013-07-06T04:19:25.640 回答
0

输出不同,因为您发布的 VB 代码等同于 C# 代码。正确的转换是:

Console.WriteLine((i * 100 \ i).ToString())

请注意,C# 对整数执行整数(截断)除法,而在 VB 中,您必须使用整数除法运算符 '\' 来执行相同的整数除法。

(更新:即使使用正确转换的整数除法运算符,我在测试中也会遇到相同的异常,所以显然这不仅仅是关于运算符)。

于 2013-07-06T05:00:29.537 回答