Posts C#->VB.NET Porting Gotchas: Math

C#->VB.NET Porting Gotchas: Math

OK, this is not supposed to be one of those C# vs. VB.NET bashing contests, so please don't let it turn into such.  I'm planning on creating a series of posts on areas where when you port code from C# to VB.NET you might run into some problems.  So to kick it off, I'm going to talk about two very common coding differences you might run into in the mathematical realm.

Take the following C# code:

<FONT color=#0000ff size=2> <P>int</FONT> result = 64 + ((<FONT color=#0000ff size=2>int</FONT>)Math.Log10((<FONT color=#0000ff size=2>double</FONT>)score) * spacing);</P> <P>Looks innocent enough.  To convert it to VB.NET you’d probably end up with:</P> <P><FONT color=#0000ff size=2>Dim</FONT> result <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT> = 64 + <FONT color=#0000ff size=2>CInt</FONT>(Math.Log10(<FONT color=#0000ff>CDbl(score))) * spacing</FONT></P> <P>However, there are several gotchas contained within here.  First, (int) in C# works more similar to Fix() in VB.NET.  So in order to get the same behavior, you need to modify your code so that the floating point portion is truncated, not rounded.</P> <P><FONT color=#0000ff size=2>Dim</FONT> result <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT> = 64 + <FONT color=#0000ff size=2>CInt</FONT>(Fix(Math.Log10(<FONT color=#0000ff>CDbl(score)))) * spacing</FONT></P> <P>Now that that is out of the way, there is still another problem looming in here.  Another behavior of the C# (int) cast is that it will work, by default, unchecked.  What does this mean?  Well, VB.NET by default will check for overflow checks at runtime, while C# doesn’t.  Not really sure why this is desirable other than performance.  Personally, I prefer VB.NET default to checking it.  Now two separate questions may be raised.  How do I handle this in VB.NET? and What about performance?</P> <P>Well, if you want to have the same exact behavior, it’s pretty easy to accomplish.  Just go into the properties for your project and under Configuration Properties - Optimizations you’ll see a Remove integer overflow checks option.  Turn it on.  This will yield the same exact behavior that C# does by default.  It will also give you increased performance by not having to use the checked IL instructions.</P> <P>I can tell your thinking to yourself that I said I prefer the VB.NET default to checking… but you know that I’m also interested in performance as well.  How can this be?  Well, to clarify my statement a bit.  I prefer having my debug build using integer overlow checks and remove them in release build.  This way I can test for these checks myself when I think they will potentially happen.</P> <P>Now back to the code conversion, what is wrong with it in the context of integer overflow checking?  Well, if the score is 0, the result of Log10 is -Infinity and if the score is a negative number, the result is NaN (Not a Number).  Obviously these values are not within the numeric range of an integer.  I’d modify the code to check for these conditions before attempting to do the math.</P> <P><FONT color=#0000ff size=2>Dim</FONT> result <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer
</FONT><FONT color=#0000ff size=2>If</FONT> score > 0 <FONT color=#0000ff size=2>Then
  </FONT>result = (64 + (<FONT color=#0000ff size=2>CInt</FONT>(Fix(Math.Log10(<FONT color=#0000ff size=2>CDbl</FONT>(score)))) * spacing))
<FONT color=#0000ff size=2>Else
  </FONT>result = 64
<FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>If</P></FONT> <P>After I tested all of the code with integer overflow enabled, I’d remove them in checked builds.</P> <P>Another math related issue I see that raises it ugly head is in the area of the division operator.  Here is a simple example in C# that could cause us problems:</P> <P><FONT color=#0000ff size=2>int</FONT> v = 10000000 / 31;</P> <P> <P></P>To convert this to VB.NET, you’d probably result in the following code: <P></P> <P><FONT color=#0000ff size=2>Dim</FONT> v <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT> = 10000000 / 31</P> <P>Looks correct, right?</P> <P>Well, try it.  You’ll find that in C# the result is 322580 and in VB.NET the result is 322581.  The difference is how the division operator works in the two languages.  C# does integer division by default, where as VB.NET does floating point devision by default.  All is not lost however since VB.NET has an integer division operator, it’s the \ (backslash).  So modifying the code as:</P> <P><FONT color=#0000ff size=2>Dim</FONT> v <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT> = 10000000 \ 31</P> <P>Will yield the same result.  Now, you probably won’t see code containing numeric values like this, it’d most likely be a couple of variables and longer equations.  So now you can see why this is potentially a very difficult “bug“ to track down after you’ve ported the code.  As a general rule, you can replace the / (slash) operator in C# with the \ (backslash) operation in VB.NET.</P> <P>That’s probably enough for this installment.  If you know of any more gotchas concerning math differences between C# and VB.NET, be sure to leave a comment.  Please refrain from other types of gotchas and save them for future installments.  If you’d like to send me issues that you’ve experienced (or are experiencing), please feel free to send me a comment using the contact link on the left.</P>

This post is licensed under CC BY 4.0 by the author.