CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Grant Killian's Blog

No, this has nothing to do with beer -- but maybe it should?

Overflows, C# and VB.Net, and IL

Students frequently ask, "What are the differences between C# and VB.Net?"  One of the first things we cover in our beginning .Net classes is how .Net languages like VB.Net and C# both produce MSIL (Microsoft Intermediate Language); IL, in turn, is used to produce the machine instructions for your program.  Most agree that the .Net language you use is more a matter of preference than anything else -- in the end, it all produces Intermediate Language code. 

The catch is that IL isn't exactly the same between C# and VB.Net -- each compiler can emit different IL instructions.  We can leverage IL to get insight into the subtle differences between VB.Net and C#. 

Let's take a simple Windows application with a button and textbox on it; we'll add a single event handler for the button.Click event like this:
VB (With Option Strict On)
Line 1) dim b as byte = byte.Parse( Textbox1.Text ) 'convert byte from Textbox's string
Line 2) b = b + byte.Parse( "200" ) 'literals are integers and Option Strict forces our explicit conversion here
Line 3) MessageBox.Show( b.ToString() )

C#
Line 1) byte b = byte.Parse( Textbox1.Text ); //convert byte from Textbox's string
Line 2) b += 200;
Line 3) MessageBox.Show( b.ToString() );

If you run this code and type the number 1 into the textbox and click your button, you'll get "201" displayed in the MessageBox for VB.Net and C#.  If you type a number large enough so we exceed the capacity of a byte in line 2, say "100", you'll get an exception in VB and you'll get "44" displayed in the C# MessageBox.

This is because by default, C# doesn't check for mathematical overflows (overflows occur when you exceed the range of a type -- a byte can contain values ranging 0-255).  So when we try to squeeze a 300 value into our byte, the first 255 is discarded leaving us with 44.  This can actually be useful; in cases where you're computing a checksum or hash based on a class, this behaviour can be important.

Digging into this example further, C# offers the checked and unchecked keywords that will set the execution context of the C# compiler.  If we typed:
checked
{
    byte b = byte.Parse( Textbox1.Text );
    b+=200;
    MessageBox.Show( b.ToString() );
}

We would force C# overflow checking for this particular block of code and raise an Overflow exception if we type "100" into our Textbox. unchecked does the opposite.  C# also offers a project compiler setting from the Project Property Page (right click on the Project in Solution Explorer); it's in Configuration Properties->Build and look at the Code Generation section.  We can toggle this behaviour on or off via the "Check for Arithmetic Overflow/Underflow" option.

I know some people like to switch this to "True" for C# projects while you're developing the program, and then switch it to "False" once you release the program -- they want to boost the performance of their application when they release it.  I don't take such a blanket approach; instead, I would pay attention to your C# code for places where arithmetic overflow is a danger and plan accordingly (via checked or unchecked).  Don't just follow the "checked for developing - unchecked for releasing" maxim unless you're completely aware of the implications!

I started this post by mentioning IL and this is an interesting opportunity to glance at the IL generated by VB.Net and C#.  Using ILDasm (I discuss ILDasm a bit here or MSDN introduces it here), we can get under the hood of .Net.  Running ILDasm on our VB.Net example yields the following in the Button1_Click method (this snippet is about half way down in the method):
  IL_0018:  call       unsigned int8 [mscorlib]System.Byte::Parse(string)
  IL_001d:  add
  IL_001e:  conv.ovf.u1

Note the "conv.ovf.u1" instruction; this is IL that forces an arithmetic overflow (ovf) check.  Use ILDasm to inspect the same C# method from our example (no checked statement or compiler option):
  IL_000b:  call       unsigned int8 [mscorlib]System.Byte::Parse(string)
  IL_0010:  stloc.0
  IL_0011:  ldloc.0
  IL_0012:  ldc.i4     0xc8
  IL_0017:  add
  IL_0018:  conv.u1

Note the "conv.u1" instruction; this is IL that DOES NOT force and arithmetic overflow check.   

[Update: Thanks to Greg Robinson for pointing out my ommision of the “Remove Integer Overflow Checks“ option on the VB.Net Project properties.  This will control the execution context of the VB.Net project like the C# “Check for Arithmetic Overflow/Underflow" option.] 

We can see that the VB.Net and C# compilers produce different IL for roughly the same functionality.  I know of a few people who write some code in pure IL, and skip the higher level languages altogether.  This is much more like writing assembly language code and I'm not into that . . . I am, however, into using ILDasm to explore the nuances of IL as it relates to C# and VB.Net.  Try it out and you'll learn a lot about your .Net language of choice.

Happy .Netting!



Comments

Grant said:

Yes, Ryan, you're right. Convert.ToByte() would be much better than string parsing.

The literal is an "integer" type in VB.Net and Option Strict On requires some conversion to byte for it to compile; Byte.Parse() probably came to mind because of the Textbox parsing on the line previous.

This would be a good candidate for Refactoring!
# March 11, 2004 3:00 AM

Greg Robinson said:

What about the "Remove integer overflow checks" and "Enable Optimization" ?
# March 29, 2004 3:17 AM

Grant said:

Good catch Greg, I've modified the post.
# March 29, 2004 4:21 AM

kik said:

good stuff
# May 11, 2004 11:01 PM

Kelly said:

Would some body know how to convert frames/byte format data into data. And vise versa.
What lib should i be looking at using c# / .net.
how would u decode bytes into data, and encode data into bytes, e.g engine sensor values to be past via a parallel port from a DSP to a PC.

Thanx heaps guys...
# May 11, 2004 11:04 PM

Shailesh said:

Thnaks. It help me to clear some basics.
# June 28, 2004 2:29 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!