C#和VB.Net中相同程序的溢出行为的差异

时间:2013-07-06 04:04:10

标签: c# vb.net

我使用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

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

3 个答案:

答案 0 :(得分: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则是另一种方式,但至少它解决了为什么会发生这种情况。 :)

修改:请参阅the answer by aquinas以获取“为什么”。

答案 1 :(得分:1)

尝试将程序更改为:

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

默认情况下,C#不会自动执行算术检查。但是,如果你转到项目属性... Build Tab..Advanced ...“[X] Check For Arithmetic overflow / underflow”,那么你将获得与VB.NET相同的行为。

答案 2 :(得分:0)

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

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

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

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