The Coding Monkey

Friday, March 24, 2006

You Have to Understand The History

One of my favorite quotes about software is from Michael Sinz:

Programming is like sex, one mistake and you have to support it for the rest of your life.

If you've programed in Visual Basic.NET for any length of time, you soon realize that this is a language that has to make a lot of child support payments. Yesterday I had to answer a question from a colleague about yet another bastard child feature in VB.NET... Array Declarations. She kept having issues because there was one extra item in the array than she was expecting. Previously she'd really only dealt with collection classes like ArrayList. So she was very confused when this statement created an array of 7 elements:

Dim pkTableCol(6) As DataColumn

After all, this statement initializes an ArrayList with a Capacity of 6 elements:

Dim pkTableCol As New ArrayList(6)

In the majority of languages like C, C++, C#, Java, and who knows how many others, you declare an array with the size of the array. The array is then indexed from 0 to Size - 1. In Visual Basic, you declare an array with the largest index. Therefore you get an array that is indexed from 0 to Index. But why on Earth would you make that decision? It's all due to the long and storied history of Visual Basic.

Visual Basic isn't like most programming languages, in that it was designed to be used by people without general computer science backgrounds. One of the "User Friendly Features" they created was arrays that were indexed starting at 1, instead of 0, and ended at Size, instead of Size - 1. While programmers are used to counting starting at 0, most non-programmers start counting at 1. While most C++ programmers would walk through an array list this:

const int ARRAY_SIZE = 6;
int array[ARRAY_SIZE];
for ( int i = 0; i < ARRAY_SIZE; i++ )
   array[i] = i * 1000;

A VB 6 programmer would have walked through an array this way:

Const ARRAY_SIZE As Integer = 6
Dim array(ARRAY_SIZE) As Integer
Dim i As Integer
For i = 1 To ARRAY_SIZE
   array(i) = i*1000
Next i

In this context, the To keyword is inclusive, so it's equivalent to <= in the C++ for loop. Unfortunately, this lead to a lot of issues. While arrays in Visual Basic worked this way, and so did some of the internal collections, may other types of lists and collections had to be 0 based because they interacted with the Windows API which is C based. So Visual Basic code was filled with mixed base arrays that confused the hell out of a lot people. You could, if you knew about it, actually change the base of an array either by using the Option Base directive, or by changing your array declarations:

Dim array(0 To ARRAY_SIZE-1) As Integer

But many people either didn't know of this feature, or just didn't bother with it. That meant that when Visual Basic.NET came along, there was a lot of old code that had to be supported for conversion from VB6 to .NET.

In .NET, no matter what language you use, arrays are indexed from 0 to Size - 1. This allows for interoperability between all the .NET languages, the Windows API, and COM controls as well. Even Visual Basic array are indexed this way. However, by changing the array declaration syntax to continue to support the old way, they supported all the old code. This way, old VB6 code would still work, there would just be one extra element in the array at index 0, which would never be used. But, the advantage is you don't get all sorts of index out of range exceptions when you convert and run your old code.

Had they changed the array declarations to come in line with the C family of languages, then you'd have to go in and modify a lot of old code if you were converting a VB6 project, because the last element wouldn't exist if you started counting at 1. Was this a good idea? Should they have forced people to modify their old code? That's up for debate. But that's all water under the bridge at this point. The decision has already been made, and now you have to support it.


Post a Comment

<< Home