KnowDotNet NetRefactor

Fun with VB.NET Arrays

by William Ryan
Print this Article Discuss in Forums

Back in the old days, arrays used to be one of my favorite tools.    Then .NET came along and I was so enamored with many of the cool things in the System.Collections namespace (System.Collection.Hashtables, System.Collections.ArrayLists, System.Collection.Queues to name a few) that I forgot all about my good old buddy the Array.  Well, I've recently decided to rekindle our friendship...

The first thing you'll need to know if you are coming from VB6 is that Array's are now 0 based.  You can still use non-zero based arrays if you really want to by calling the NewArray function which is provided in the Compatibility library but don't do it.  There are many good reasons to not do it and only one (not very good one)to use it (I don't want to change).  So, let's pretend it doesn't exist.

To declare an array, it's very easy:

Dim ArrayOfInts(10) As Integer


We can now fill up the array like this:

ArrayOfInts(0) = 1
ArrayOfInts(1) = 2
....until 10


It's bad practice to declare bounds that you won't use because arrays are stored contiguously in memory, so as soon as you declare it, x number of bytes is reserved.

I prefer abbreviated syntax, so you can also declare the array like this:

Dim ArrayOfInts() As Integer = {1,2,3,4,5,6,7,8,9}


You can also declare the array with unknown bounds and then initialize it later:

Dim ArrayOfInts() as Integer

ArrayOfInts = New Integer() {1,2,3,4,5,6,7,8,9}


To reference any given value of the array, you refer to it by its index.  So, if you wanted to find out what the first value in the array is you could do this:

Dim x as Integer = MyArrayOfInts(0)


One relatively unknown feature of VB.NET is that there's another way to declare an array.  You see, for backward compatibility, Microsoft kept the old VB6 syntax  for declarations.  However, this will work as well:

Dim ArrayOfInts as Integer()


This method will seem more intuitive to programmers with a C background.  I prefer the latter because to me, an Integer isn't the same as an Integer() so this is more clear to me.  Moreoever, it's consistent with C style as I mentioned above, so I don't have to rethink what I'm doing when I'm flipping between C# and VB.NET.  The only downside is that you can't declare and instantiate the array in one line.

There are two ways to walk through an array and utlimately, which method you use is a matter of preference:

Assuming we declared and populated MyArrayOfInts as above

Dim i As Integer

For i = 0 to MyArrayOfInts.Length-1
     Debug.WriteLine(MyArrayOfInts(i)
Next


If you have Visual Studio .NET 2003 you can also use a more C like syntax with the For loop:

For i as Integer = 0 to MyArrayOfInts.Length-1
    Debug.WriteLine(MyArrayOfInts(i)
Next


However, arrays implement the IList interface so you can enumerate it as well:

Dim i As Integer

For Each i in MyArrayOfInts
    Debug.WriteLine(i)
Next


As you know, one of the favorite pasttimes of programmers is debating minutae and if you mention performance, you are assured to get into a "which way is better" argument.  The other favorite argument is readability.  There's not one programmer I know who will admit they write code that's hard to read/understand, but there's a lot of unreadable code out there, so someone's wrong.  

I tend to lean on the 'fastest is best' side when talking about performance and the 'methodology makes code more readable, and 1 line of code is usually more readable than 5' side when talking about readability.  So I'm in a real quandry on this one.  Personally, the For Each syntax is more readable to me.  However, Indexed based enumeration is usually faster.  In most cases, you'll find that the performance difference is undetectable.  At least in this one though, the benefits of each are pretty straightforward.

Arrays have some other cool features that you may find helpful.

Provided you have your array sorted, you can use the BinarySearch method for very fast searching.  However, and this is a big however, the whole premise of a Binary Search is that it's done one a Sorted List.  If you try a Binary Search on an array that isn't sorted, it won't blow up on you.  However, it wil return results that are anybody's guess.  This may seem like something every CS101 student knows, but I've seen more people than I care to admit claiming BinarySearch is buggy because they didn't sort their array first.

'Would return 8 as the position where it exists if the array
'were initialized as shown above
Array.BinarySearch(MyIntArray, 9)



A corrolary to this is the SharedSort method.  The only catch here is that whatever objects you sort must implement the IComparable Interface.  After all, it's easy to sort Integers, but how could the framework possibly know how to sort Foo objects if Foo doesn't have a mechanism to tell you what is greater than or less than what?

Array.Sort(MyIntArray)


Similar to sort is the Shared Reverse method.  The requirements are the same, your objects need to implement IComparable for the same reasons that apply to sort.

Array.Reverse(MyIntArray)


Another feature is the Clear method.  So, if you clear element 2 for instance and you try referencing its length property afterward, you are going to raise a null reference exception.

Array.Clear(MyIntArray, 0, 1)


The SharedCopy method does exactly what you think it will do, copy an array or pieces of an array to another array. Remember though, you may me copying reference types so approach it accordingly

Array.Copy(MyIntArray, MySecondIntArray, 2)



The Clone method is similar to copy, it makes a clone of  the original array.  However, just like copy, you have to be careful when you use clone becuase it makes a Shallow Copy (Shallow Clone) of the objects if they are reference types.  As such, if you manipulate the second array it will change the values of the first array and vice versa!  Remember also that this has NOTHING to do with Passing ByVal or ByRef.   You can pass the cloned array ByVal, change its values, and both Array1 and Array2 will have their values changed!

MySecondIntArray = MyIntArray.Clone


The CopyTo method is another one I really love.  This can copy the elements of an array to any object implementing the IList interface.  On catch here though, it's only supported in the 1.1 version of the framework.

MyArrayList = Array.CopyTo(MyIntArray, 0)


Another method you may use frequently is the
GetValue method.

'Will return the value of the 9th element if there is one.
Dim i as Integer = MyIntArray.GetValue(9)



This is hardly an exhaustive discussion of the powerful Array object, but it covers most of the common functions that you'll come across.  I will admit that most of the other collection objects can do most of this for you, but what you use and how you use it is up to you.

Writing Add-Ins for Visual Studio .NET
Writing Add-ins for Visual Studio .NET
by Les Smith
Apress Publishing