简体   繁体   中英

Difference in overflow behavior for same program in C# and VB.Net

I ran a program in .Net 3.5 using C# which works fine

try
{
    int i = 2147483647;

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

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

When I run this program in C#, I don't get an exception (it outputs "0"). But when I run this program in VB.Net it results in "Arithmetic operation resulted in an overflow" exception

Try
    Dim i As Integer = 2147483647

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

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

Why the different behavior between these two languages?

Perhaps looking at the IL will clarify... Simplifying your code a bit:

C#:

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

generates the following 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

while the VB version:

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

generates this IL, slightly different:

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

As you can see, VB is calling mul.ovf , which is "multiply, and check for overflow", and C# is calling mul which does not check for overflow.

Perhaps it doesn't answer your question as to why C# does it one way and VB the other, but at least it answers why it is happening. :)

Edit: see the answer by aquinas to get the "why".

Try changing your program to this:

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

C# doesn't automatically perform arithmetic checking by default. However, if you go to project properties...Build Tab..Advanced..."[X] Check For Arithmetic overflow/underflow" then you will get the same behavior as VB.NET by default.

The output is different because the VB code you posted is not equivalent to the C# code. The correct conversion is:

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

Note that C# performs integer (truncating) division on integers, while in VB you have to use the integer division operator '\\' to do the same integer division.

(update: even when using the correctly converted integer division operator, I also get the same exception in my test, so obviously it's not just about the operator).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM