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?
|
|
|
|
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
|
|
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.