September 6, 2005
Integers in VB.NET...
... or, why you should RTFM.
Let's say you have a set of devices. Let's also say you have a computer set up to receive and parse an array of bytes that these things send. One part of this data stream is an identifier. It's a two-byte (16-bit) integer, so I create a Short (a.k.a. Int16).
This works a great deal of the time, since the Int16 coming in is usually something like 18. But every once in a while, I see something like 34,000.
All the programmers are now saying, as long as that Int16 is unsigned you're golden. They would be right.
As an aside for the non-programmers, there are actually two types of number to a computer: Signed and unsigned. Unsigned numbers simply count up from zero until they run out of space. In the case of an Int16, that's 65,535. Signed numbers use one of the bits to tell you whether they're positive or negative, so they can't count as far. A signed Int16 runs from -32,768 to 32,767. Note that it covers the same range, but since it has to differentiate between positive and negative it doesn't go as far in either direction.
Now, let's get back to my program. If you say
Dim MyInt as Int16
you get a signed Int16. That number runs to a maximum of 32,767. Which means that the value of 34,000-ish I was receiving was too much for it to handle.
VB.NET will throw an exception when you do this. But it's not enough of an exception to make the program fail. If you're using threads, though, the thread will never complete and just sit around like a member of the undead. And if you're being a little lazy about closing your threads they'll hang around forever.
Well, by "forever" I mean until the CPU tops out trying to keep track of them all. These zombie threads will eventually bring your machine to its knees and require manual intervention in the form of a trip to Task Manager Land.
There are two solutions. On the one hand you can declare your variable as a UInt16 (an unsigned 16-bit integer) or you can just make the thing an Int32 (a 32-bit integer). Since I was looking for a quick answer, I went the Int32 route and decided to just eat those extra 2 bytes of RAM -- I think the 512 MB on the box will forgive me. The techincally correct way would be to declare it unsigned. Either works, and there's probably no appreciable difference between the two until you start getting a thousand reports or so a minute.
- If the docs say it's unsigned, make sure your variable is either unsigned or oversized.
- Put everything in a try block, even stuff that "shouldn't" throw an exception.
Trust me, you'll be a lot happier that way.