Difference between C and VB simple add

Sometimes differences between C# and VB could be subtle, for example consider these very simple two snippets of code, what they will print?

1
2
3
4
5
6
7
Sub  Main()  
        Console.WriteLine(Result  is    +  Sum(Integer.MaxValue,  1))  
EndSub  
  
PublicFunction  Sum(ByVal  a  AsInteger,  ByVal  b  AsInteger)  
Return  a  +  b  
EndFunction
1
2
3
4
5
6
7
static void  Main(string[]  args)  {  
Console.WriteLine(Result  is    +  Sum(Int32.MaxValue,  1));  
  }  
  
public static Int32  Sum(Int32  a,  Int32  b)  {  
return  a  +  b;  
  }

The first snipped written in VB throws a System.OverflowException, because the result of the operation cannot be stored into an integer value. The behavior of C# can be more surprising because it print Result is -2147483648 showing a result that is clearly wrong. This example shows that VB and C# have very different semantic even for basic operation. But what is the reason for such a different behavior? If we look at MSIL code we can see that VB compiler produces this code

L\_0002:  ldarg.1    
    L\_0003:  add.ovf    
    L\_0004:  box  [int32](http://www.aisto.com/roeder/dotnet/Default.aspx?Target=code://mscorlib:2.0.0.0:b77a5c561934e089/System.Int32 "int32")  

As you can see the add operation gets translated with opcode add.ofv, where ofv means overflow. This particular operation throws an exception if the result of the operation will result in a overflow. C# generates this snippet.

L\_0002:  ldarg.1    
    L\_0003:  add    
    L\_0004:  stloc.0

Generated MSIL is different because C# compiler use the add opcode that will not check for an overflow. The question is: why such different behavior? VB.NET descends from VB6 where all arithmetic operations are checked, so this semantic is maintained even if for.NET version, C# descends from C++ where aritmetic operation does not check for an overflow. The primary reason is efficiency, let’s look at real IA32 code generated by the JIT compiler through disassembly window. This is the assembly generated for the add.ofv opcode (VB).

Dim  result  As  Integer  =  a  +  b  
0000002e    mov                  eax,ebx    
00000030    add                  eax,dword  ptr  [ebp-40h]    
00000033    jno                  0000003A    
00000035    call                79747E72    
0000003a    mov                  dword  ptr  [ebp-44h],eax  

After the add operation there is a jno opcode that means “ Jump if not overflow “, if the operation will result in a overflow, the instruction does not jump and instruction at offset 35 calls a system routine that will throw the exception. The cost of checking overflow is a branch instruction after every arithmetic operation, for this reason C# compiler does not insert overflow check instruction for arithmetic operation. If you don’t like this, you can force C# compiler to insert overflow checking instruction with checkedkeyword

1
2
3
checked  {  
return  a  +  b;  
}

With the checked keyword we can choose to do checked operation only for specific parts of the code. VB is less flexible, because has a compiler operation that will disable overflow check for all the assembly, not showing the granularity of C#.

Alk.