An array is an indexed collection of objects, all of the same type. In this chapter, you will learn to work with three types of arrays: one-dimensional arrays, multidimensional rectangular arrays, and multidimensional jagged arrays.
To picture a one-dimensional array, imagine a series of mailboxes, all lined up one after the other. Each mailbox can hold exactly one object (one letter, one box, etc.). It turns out that all the mailboxes must hold the same kind of object; you declare the type of object the mailboxes will hold when you declare the array.
A multidimensional array allows you to create rows of mailboxes, one above the other. If all the rows are the same length, you have a rectangular array. If each row of mailboxes is a different length, you have a jagged array.
You can think of a multidimensional array as being like a grid of rows and columns in which each slot (mailbox) contains information. For example, each column might contain information pertinent to an employee. Each row would contain all the information for a single employee.
Most often you will deal with one-dimensional arrays, and if you do create multi-dimension arrays they will be two-dimensional�but larger multidimensional arrays (3D, 4D, etc.) are also possible.
A jagged array is a type of two-dimensional array in which each row can have a different number of columns. A jagged array is less of a grid, and more of an array of arrays�that is, an array in which the elements in one array are other arrays. This allows you to group a few arrays of varying sizes into a single array. For example, you might have an array of ten buttons, and a second array of five listboxes, and a third array of seven checkboxes. You can group all three into a jagged array of controls.
In order to declare an array, you must use a constructor, but you are free to use it in a variety of ways. For example, you can use either an implicit or an explicit constructor, as in the following:
Dim myIntArray( ) As Integer ' implicit constructor Dim myIntArray As Integer = New Integer( ) {}' explicit constructor
Which type of constructor you use is a matter of personal preference.
Alternatively, you can specify the initial size of the array (that is, how many elements it will hold):
Dim myIntArray(6) As Integer ' implicit constructor 6 members Dim myIntArray As Integer = new Integer(6) ' explicit, 6 members
In all of these examples, the parentheses tell the VB.NET compiler that you are declaring an array, and the type specifies the type of the elements it will contain. In all of the arrays we have declared so far, myIntArray is an array of Integers. It is important to distinguish between the array itself (which is a collection of elements) and the component elements within the array. myIntArray is the array; its elements are the six integers it holds.
|
Arrays are zero-based,[1] which means that the index of the first element is always zero, as in myArray(0). The second element is element 1. Index 3 indicates the element that is offset from the beginning of the array by 3 elements�that is, the fourth element in the array. You access element 3 by writing:
[1] It is possible to create arrays that are not zero-based, but only with multidimensional arrays, and it is rarely a good idea. To do so you must use the CreateInstance( ) method of the Array class, and the resulting arrays are not compliant with the Common Language Specification.
myArray(3) ' return the 4th element (at offset 3)
You declare the initial size of the array (that is, how many elements it will hold) by specifying the upper bounds of the array. Both of the following declarations specify an array with seven elements; the first uses an implicit constructor for this purpose, the second an explicit constructor:
Dim myIntArray(6) As Integer ' implicit constructor, 7 members Dim myIntArray As Integer = New Integer(6) {}' explicit, 7 members
Note that these arrays have seven elements (not six) because with an upper bound of 6, the element indices are 0,1,2,3,4,5,6 for a total of 7 elements.
You can change the size of an array at any time using the ReDim keyword. Changing the size is commonly referred to as redimensioning the array.[2]
[2] "Redimensioning" is a terribly misleading term. It suggests you are changing the dimensions of the array (which is described later in this chapter); in fact you are changing the array's size. Redimensioning should more properly be called resizing the array, but the terminology was established early in the history of Visual Basic, and it's too late now; we're stuck with the term redimensioning.
There are two ways to redimension an array. If you use the Preserve keyword, the data in the array is preserved; otherwise, all the data in the array is lost when it is resized using ReDim.
You can resize an array named myArray from its current size to 50 by writing:
ReDim myArray(50)
You can make the same change to myArray, but preserve the existing data in the array by writing:
ReDim preserve myArray(50)
At times, you will not want to resize an array to a particular size but rather to expand the array by a particular increment. For example, if you are adding items to an array, and you find you're about to run out of room, you might add 50 to the current size of the array. You can use the UBound property of the array which returns the current upper bound of the array. The following line resizes myArray to 50 elements larger than its current size:
ReDim Preserve myArray(UBound(myArray) + 50)
When you create an array of value types, each element initially contains the default value for the type stored in the array. (See Table 5-2.) The following declaration creates an array (myIntArray) of six integers, each of whose value is initialized to 0, the default value for Integer types:
'six Integers with default values Dim myIntArray As Integer = New Integer(6) {}
With an array of reference types, the elements are not initialized to their default values. Instead, they are initialized to Nothing. If you attempt to access any of the elements in an array of reference types before you have specifically initialized them, you will generate an exception (exceptions are covered in Chapter 11).
Assume you have created a Button class. You declare an array of Button objects (thus reference types) with the following statement:
Dim myButtonArray As Button( )
and you instantiate the actual array, to hold four Buttons, like this:
myButtonArray = New Button(3){}
Note that you can combine the two steps and write:
Dim myButtonArray As Button( ) = New Button(3) {}
In either case, unlike with the earlier integer example, this statement does not create an array with references to four Button objects. Since Button objects are reference types, this creates the array myButtonArray with four Nothing, or null, references. To use this array, you must first construct and assign a Button object for each reference in the array. This is called populating the array. You can construct the objects in a loop that adds them one by one to the array. Example 9-1 illustrates creating an array of value types (integers) and of reference types (Employee objects).
Option Strict On Imports System 'a simple class to store in the array Public Class Employee Private empID As Integer 'constructor Public Sub New(ByVal empID As Integer) Me.empID = empID End Sub End Class Class Tester Public Sub Run( ) Dim intArray As Integer( ) Dim empArray As Employee( ) intArray = New Integer(5) {} empArray = New Employee(3) {} 'populate the array Dim i As Integer 'for indices 0 through 3 For i = 0 To empArray.Length - 1 empArray(i) = New Employee(i + 5) i = i + 1 Next End Sub Shared Sub Main( ) Dim t As New Tester( ) t.Run( ) End Sub End Class
Example 9-1 begins by creating a simple Employee class to add to the array. When Run( ) begins, two arrays are declared, one of type Integer, the other of type Employee:
Dim intArray As Integer( ) Dim empArray As Employee( )
The Integer array is populated with Integers set to zero. The Employee array is initialized with Nothing references.
|
You must populate the Employee array before you can refer to its elements:
For i = 0 To empArray.Length - 1 empArray(i) = New Employee(i + 5) i = i + 1 Next
The exercise has no output. You've added the elements to the array, but how do you use them? How do you refer to them?
You access a particular element within an array using parentheses and a numeric value knows as an index, or offset. You access element 3 by writing:
myArray(3) ' return the 4th element (at offset 3)
Because arrays are objects, they have properties. One of the more useful properties of the Array class is Length, which tells you how many objects are in an array. Array objects can be indexed from 0 to Length-1. That is, if there are five elements in an array, their indices are 0,1,2,3,4.
In Example 9-2, you create an array of Employees and an array of integers, populate the Employee array, and then you print the values in each array.
Option Strict On Imports System Namespace ArrayDemo 'a simple class to store in the array Public Class Employee Private empID As Integer 'constructor Public Sub New(ByVal empID As Integer) Me.empID = empID End Sub 'New Public Overrides Function ToString( ) As String Return empID.ToString( ) End Function 'ToString End Class 'Employee Class Tester Public Sub Run( ) Dim intArray( ) As Integer Dim empArray( ) As Employee intArray = New Integer(5) {} empArray = New Employee(3) {} 'populate the array Dim i As Integer For i = 0 To empArray.Length - 1 empArray(i) = New Employee(i + 5) Next i Console.WriteLine("The Integer array...") For i = 0 To intArray.Length - 1 Console.WriteLine(intArray(i).ToString( )) Next i Console.WriteLine(ControlChars.Lf + "The Employee array...") For i = 0 To empArray.Length - 1 Console.WriteLine(empArray(i).ToString( )) Next i End Sub 'Run Shared Sub Main( ) Dim t As New Tester( ) t.Run( ) End Sub 'Main End Class 'Tester End Namespace 'ArrayDemo Output: The Integer array... 0 0 0 0 0 The Employee array... 5 6 7
Example 9-2 starts with the definition of an Employee class that implements a constructor that takes a single integer parameter. The ToString( ) method inherited from Object is overridden to print the value of the Employee object's employee ID.
The Run( ) method declares and then instantiates a pair of arrays. The Integer array is automatically filled with Integers whose value is set to zero. The Employee array contents must be constructed by hand (or will contain values set to Nothing). To populate the array by hand, you construct each Employee object in turn, adding them to the Array as they are created:
Dim i As Integer For i = 0 To empArray.Length - 1 empArray(i) = New Employee(i + 5) Next i
In this For loop, each Employee is created with a value equal to five more than its index in the array. These are arbitrary values used here to illustrate how to add Employee objects to the array.
Finally, the contents of the arrays are printed to ensure that they are filled as intended. The five Integers print their value first, followed by the three Employee objects.
The For Each looping statement allows you to iterate through all the items in an array (or other collection), examining each item in turn. The syntax for the For Each statement is:
For Each identifier In collection statement Next
The For Each statement creates a new object that will hold a reference to each of the objects in the collection, in turn, as you loop through the collection. For example, you might write:
Dim intValue As Integer For Each intValue In intArray
Each time through the loop, the next member of intArray will be assigned to the integer variable intValue. You can then use that object to display the value, as in:
Console.WriteLine(intValue.ToString( ))
Similarly, you might iterate through the Employee array:
Dim e As Employee For Each e In empArray Console.WriteLine(e) Next
In the case shown here, e is an object of type Employee. For each turn through the loop, e will refer to the next Employee in the array.
Example 9-3 rewrites the Run( ) method of Example 9-2 to use a For Each loop, but is otherwise unchanged.
Option Strict On Imports System Public Sub Run( ) Dim intArray( ) As Integer Dim empArray( ) As Employee intArray = New Integer(5) {} empArray = New Employee(3) {} 'populate the array Dim i As Integer For i = 0 To empArray.Length - 1 empArray(i) = New Employee(i + 5) Next i Console.WriteLine("The Integer array...") Dim intValue As Integer For Each intValue In intArray Console.WriteLine(intValue.ToString( )) Next Console.WriteLine("The Employee array...") Dim e As Employee For Each e In empArray Console.WriteLine(e) Next End Sub 'Run Output: The Integer array... 0 0 0 0 0 The Employee array... 5 6 7
The output for Example 9-3 is identical to Example 9-2. However, rather than creating a For statement that measures the size of the array and uses a temporary counting variable as an index into the array:
For i = 0 To empArray.Length - 1 Console.WriteLine(empArray(i).ToString( )) Next i
you now iterate over the array with the For Each loop which automatically extracts the next item from within the array and assigns it to a temporary object you've created in the head of the statement. In the following case, the temporary object is of type Employee (it is a reference to an Employee object) and is named e:
Dim e As Employee For Each e In empArray Console.WriteLine(e) Next
Since the object extracted from the array is of the appropriate type (i.e., e is a reference to an Employee), you can call any public method of Employee.
|
Rather than assigning elements to the array as we have done so far, it is possible to initialize the contents of an array at the time it is instantiated. You do so by providing a list of values delimited by curly braces ({}). VB.NET provides two different syntaxes to accomplish the same task:
Dim myIntArray1( ) As Integer = { 2, 4, 5, 8, 10} Dim myIntArray2( ) As Integer = New Integer(4) { 2, 4, 6, 8, 10 }
There is no practical difference between these two statements, and most programmers will use the shorter syntax because we are, by nature, lazy. We are so lazy, we'll work all day to save a few minutes doing a task�which isn't so crazy if we're going to do that task hundreds of times! Example 9-4 again rewrites the Run( ) method of Example 9-4, this time demonstrating initialization of both arrays.
Option Strict On Imports System Public Sub Run( ) Dim intArray As Integer( ) = {2, 4, 6, 8, 10} Dim empArray As Employee( ) = _ {New Employee(5), New Employee(7), New Employee(9)} Console.WriteLine("The Integer array...") Dim theInt As Integer For Each theInt In intArray Console.WriteLine(theInt.ToString( )) Next theInt Console.WriteLine("The Employee array...") Dim e As Employee For Each e In empArray Console.WriteLine(e.ToString( )) Next e End Sub 'Run Output: The Integer array... 2 4 6 8 10 The Employee array... 5 7 9
What do you do if you need to pass parameters to a method but you don't know how many parameters you'll want to pass? It is possible that the decision on how many parameters you'll pass in won't be made until runtime.
VB.NET provides the ParamArray keyword to allow you to pass in a variable number of parameters. As far as the client (the calling method) is concerned, you pass in a variable number of parameters. As far as the implementing method is concerned, it has been passed an array, and so it can just iterate through the array to find each parameter!
For example, you can create a method called DisplayVals( ) that takes integers as parameters and displays them to the console:
Public Sub DisplayVals(ByVal ParamArray intVals( ) As Integer) Dim i As Integer For Each i In intVals Console.WriteLine("DisplayVals {0}", i) Next i End Sub 'DisplayVals
The ParamArray keyword indicates that you can pass in any number of integers, and the method will treat them as if you had passed in an array of integers. Thus you can call this method from Run( ) with:
DisplayVals(5, 6, 7, 8)
And the DisplayVals( ) method will treat this exactly as if you had written:
Dim explicitArray( ) As Integer = {5, 6, 7, 8} DisplayVals(explicitArray)
And in fact, you are free to create such an array and send it in as the parameter, as demonstrated in Example 9-5.
Option Strict On
Imports System
Namespace ArrayDemo
Class Tester
Public Sub Run( )
Dim a As Integer = 5
Dim b As Integer = 6
Dim c As Integer = 7
Console.WriteLine("Calling with three Integers")
DisplayVals(a, b, c)
Console.WriteLine("Calling with four Integers")
DisplayVals(5, 6, 7, 8)
Console.WriteLine("Calling with an array of four Integers")
Dim explicitArray( ) As Integer = {5, 6, 7, 8}
DisplayVals(explicitArray)
End Sub 'Run
'takes a variable number of Integers
Public Sub DisplayVals(ByVal ParamArray intVals( ) As Integer)
Dim i As Integer
For Each i In intVals
Console.WriteLine("DisplayVals {0}", i)
Next i
End Sub 'DisplayVals
Shared Sub Main( )
Dim t As New Tester( )
t.Run( )
End Sub 'Main
End Class 'Tester
End Namespace 'ArrayDemo
Output:
Calling with three Integers
DisplayVals 5
DisplayVals 6
DisplayVals 7
Calling with four Integers
DisplayVals 5
DisplayVals 6
DisplayVals 7
DisplayVals 8
Calling with an array of four Integers
DisplayVals 5
DisplayVals 6
DisplayVals 7
DisplayVals 8
In Example 9-5, the first time you call DisplayVals( ) you pass in three integer variables:
Dim a As Integer = 5 Dim b As Integer = 6 Dim c As Integer = 7 DisplayVals(a, b, c)
The second time you call DisplayVals( ) you use four literal constants:
DisplayVals(5, 6, 7, 8)
In both cases, DisplayVals( ) treats the parameters as if they were declared in an array. In the final invocation, you explicitly create an array and pass that as the parameter to the method:
Dim explicitArray( ) As Integer = {5, 6, 7, 8} DisplayVals(explicitArray)
Top |