The .NET Array Class


Managed arrays in the .NET Framework all inherit from System::Array, which means that every managed array has a number of useful properties and methods. These properties and methods are summarized in the following two tables.

Property

Description

IsFixedSize

Returns true if the array has a fixed size. Always returns true, unless overridden by a derived class.

IsReadOnly

Returns true if the array is read-only. Always returns false, unless overridden by a derived class.

IsSynchronized

Returns true if the array is thread-safe (synchronized). Always returns false, unless overridden by a derived class.

Length

Returns the total number of elements in all dimensions of the array.

Rank

Returns the number of dimensions in the array.

SyncRoot

Returns a pointer to an object that can be used to synchronize access to the array.

Method

Description

BinarySearch

Static method that searches a single-dimensional array for a value, using a binary search algorithm.

Clear

Static method that sets all or part of an array to zero or a null reference.

Clone

Creates a shallow copy of the array.

Copy

Static method that copies all or part of one array to another array, performing type downcasting as required.

CopyTo

Method that copies all or part of one single-dimensional array to another.

GetEnumerator

Returns an enumerator for the array. See the “Enumerators” section later in this chapter for details.

GetLength

Returns the number of elements in a specified dimension as an integer.

GetLowerBound

Returns the lower bound of a specified dimension as an integer.

GetUpperBound

Returns the upper bound of a specified dimension as an integer.

GetValue

Returns the value at a specified position in a single- dimensional or multidimensional array.

IndexOf

Static method that returns the index of the first occurrence of an element in an array or a part of an array.

Initialize

Initializes an array of value types by calling the default constructor of the value type. This method must not be used on arrays of reference types.

LastIndexOf

Static method that returns the index of the last occurrence of an element in an array or a part of an array.

Reverse

Static method that reverses the order of the elements in all or part of a single-dimensional array.

SetValue

Sets an array element to a specified value.

Sort

Static method that sorts the elements in a single- dimensional array.

Basic Operations on Arrays

Unlike traditional C++ arrays, managed arrays are objects, and they “know” how many dimensions they have and how many elements they contain. The following exercise introduces you to some of the basic functionality in the System::Array class.

  1. Open Visual Studio if it isn’t already open, and create a new Visual C++ Console Application (.NET) project named SysArray.

  2. At the top of the _tmain function, add declarations for some loop counters and a two-dimensional array of 32-bit integers, like this:

    // Declare loop counters int i,j,k; // Create a multidimensional array of Int32s Int32 pn[,] = new Int32[3,2];

    This is the array that you’ll use for exploring the features of the System::Array class in the rest of this section.

  3. Because this is a managed array, it inherits directly from System::Array, so you can use the Rank and Length properties of the Array class to find out the rank (number of dimensions) and total length of the array.

    Console::WriteLine("Rank is {0}", __box(pn->Rank)); Console::WriteLine("Length is {0}", __box(pn->Length));

    When you run this code, you should find that the rank is two and the total length is six, which matches the declaration.

  4. The GetLength method—not to be confused with the Length property—returns the size of any one dimension of the array, so you can print out the sizes of each dimension like this:

    // Print out the array dimension information for (i=0; i<pn->Rank; i++) Console::WriteLine("Dimension {0} is of size {1}", __box(i), __box(pn->GetLength(i)));

    Now that you’ve got an array and can find out how large each dimension is, you need to know how to get and set elements in the array.

  5. Add the following nested loops to the end of your code:

    // Fill the array with values for (j=0; j<pn->GetLength(0); j++) for (k=0; k<pn->GetLength(1); k++) pn[j,k] = (j+1)*(k+1);

    The outer loop iterates over the rows, while the inner loop iterates over the columns, and the [x,y] notation is used to reference the array elements. The Array class also has the SetValue method, which provides an alternative way of setting values for those languages that don’t support C++-style array notation.

    // Put ’10’ in array element [1,1] pn->SetValue(__box(10), 1, 1);

    Note that when using SetValue, you have to box the value to be inserted into the array because SetValue expects a pointer to a reference type.

  6. Print out the values in the array by using a similar pair of nested loops.

    // Print out the array data for (j=pn->GetLowerBound(0); j<=pn->GetUpperBound(0); j++) for (k=pn->GetLowerBound(1); k<=pn->GetUpperBound(1); k++) Console::WriteLine("pn[{0},{1}] = {2}", __box(j), __box(k), __box(pn[j,k])); 

    Once again, the outer loop iterates over the rows while the inner loop iterates over the columns. In this case, the GetLowerBound and GetUpperBound methods return the indices of the lower and upper bounds. The argument to GetUpperBound and GetLowerBound is the dimension of the array whose bound you want to find. In C++, the lower bound is invariably 0 and the upper bound can be obtained using the GetLength method, so these are mainly useful in other languages where it might be common to have arrays with arbitrary lower and upper bounds.

All the integer values have to be boxed before they can be printed out. As an alternative to boxing the array value, you can use the GetValue method to access an array element, which returns an object reference.

Console::WriteLine("pn[{0},{1}] = {2}", __box(j), __box(k), pn->GetValue(j,k));

More Advanced Array Operations

You can now create arrays, find out how many dimensions they have and how large they are, and set and retrieve values. This section introduces some of the more advanced operations supported by the Array class, such as copying, searching, and sorting.

Copying Array Elements

The following exercise shows you how to use the Copy method to copy part of one array to another.

  1. Open the project you were using in the previous exercise if you’ve closed it.

  2. At the end of the _tmain function, create a second two-dimensional array the same size and type as the original.

    // Create another multidimensional array of Int32s Int32 pn2[,] = new Int32[3,2];
  3. Add some code to fill the new array with a constant value.

    // Fill the array with a constant value for (j=0; j<pn2->GetLength(0); j++) for (k=0; k<pn2->GetLength(1); k++) pn2[j,k] = 47;
  4. To copy some values over from the first array to the second, use the static Copy method.

    // Copy two values from pn to pn2 System::Array::Copy(pn,0, pn2,2, 2); 

    This method lets you copy all or part of one array into another. The first two arguments are the source array and the index from which to start copying. The second two are the destination array and the starting index from which elements are to be replaced. The final argument is the number of elements to be copied. In this case, you’ve copied two elements from pn into the middle of pn2, which you’ll be able to see if you add code to print the contents of pn2.

Searching

It’s common to want to search an array to see whether it contains a specific entry, and you can do so by using the IndexOf and LastIndexOf methods.

  1. Create a new Visual C++ Console Application (.NET) project named Strings.

  2. Open the Strings.cpp source file, and add the following code to the top of the _tmain function to create an array of strings:

    // Create an array of strings String* sa[] = { S"Dog", S"Cat", S"Elephant", S"Gerbil", S"Dog", S"Horse", S"Pig", S"Cat" }; // Check the length Console::WriteLine(S"sa has length {0}", __box(sa->Length));

  3. The IndexOf and LastIndexOf functions both let you search to see whether a particular object occurs in the array. Add the following code the _tmain function:

    // Search for a value String* s = S"Dog"; int pos = Array::IndexOf(sa, s); Console::WriteLine(S"Index of s in sa is {0}", __box(pos)); // Search for the next occurrence pos = Array::IndexOf(sa, s, pos+1); Console::WriteLine(S"Next index of s in sa is {0}", __box(pos));

    The call to IndexOf finds the first occurrence of string Dog in the array and returns its index, which in this case is 0. The second call, to an overload of IndexOf, searches for an occurrence beginning at a given offset. Because the search is starting just past the first occurrence, the index returned is that of the second occurrence, which is 4. A third overload lets you search within a portion of the array.

Note

If the value isn’t found, the index returned will be one less than the lower bound of the array, which in C++ will usually mean a value of -1.

LastIndexOf works in the same way as IndexOf but starts searching from the other end of the array.

Sorting

The static Array::Sort method and its overloads give you a way to sort an array or a part of an array, while Array::Reverse lets you reverse the order of elements. Try adding the following code to the _tmain routine:

Array::Sort(sa); Array::Reverse(sa); for (int i=0; i<sa->get_Length(); i++) Console::WriteLine(sa[i]);

When you run the program, you should get the elements of the array printed in reverse order, from Pig back to Cat.

One valuable overload to Sort lets you provide two arrays, one of which contains keys used to define the sort order. Here’s an exercise to show you how this works.

  1. Continue with the Strings project. The sa array currently contains the following entries:

    Pig Horse Gerbil Elephant Dog Dog Cat Cat
  2. After the calls to Sort and Reverse, add a new array:

    Int32 keys[] = { 6, 4, 3, 5, 2, 2, 1, 1 };

    This array contains the keys that you’re going to use to sort the array of animal names. They reflect my preferences—cats are number one, while pigs come in at number six—so feel free to change them if you like.

  3. Add another call to Sort, specifying both arrays:

    Array::Sort(keys, sa);

    The keys array is sorted, and the elements in sa are sorted into exactly the same order. When you run the code and print out the array, you’ll find that the elements have been sorted from Cat to Pig.

start sidebar
The IComparable Interface

Any type that wants to be used in the Sort method has to implement the IComparable interface, which has one member, CompareTo. When CompareTo is invoked on an object, it gets passed a reference to another object. The function returns 0 if the two instances are equal, a negative value if the object passed in is greater than the instance calling the function, and a positive value if the object passed in has a lesser value.

end sidebar

Enumerators

The GetEnumerator method returns an enumerator that allows you to iterate over the elements of the collection, in rather the same way that ForEach iterates over collections in Microsoft Visual Basic or foreach does in C#.

An enumerator provides programmers with a high-level way to iterate over the items in a collection without having to know about how the collection is actually implemented. So, you can use an enumerator to iterate over the contents of an array or a linked list in exactly the same way, without knowing exactly how you get from one element to another in the underlying data structures. Many of the collections in the .NET Framework support the enumerator model.

A call to GetEnumerator returns you a pointer to an IEnumerator, which has two methods and one property that you can use:

  • MoveNext advances the enumerator to the next element in the collection.

  • Reset moves the enumerator back to just before the first element in the collection.

  • Current returns a reference to the current element.

In this next exercise, you’ll use an enumerator to list the elements in the String array.

  1. Continue with the Strings project, and add the following using declaration to the start of the program:

    using namespace System::Collections;

    The IEnumerator interface is defined in the System::Collections namespace, so it’s easier to use enumerators if you add a using declaration for the namespace.

  2. Add the following code to the end of the _tmain function:

    IEnumerator* ie = sa->GetEnumerator(); while (ie->MoveNext()) Console::WriteLine(ie->Current);

    You’ll notice several things about this code. To begin with, the enumerator starts off positioned before the first element, so you need to call MoveNext once to get to the first element. When there are no more elements to retrieve, calls to MoveNext return false. The property Current retrieves the current object but doesn’t move the pointer, so you’ll get the same value back until you call MoveNext again. The Current property also returns a general Object pointer, so you’ll often need to cast this pointer to the actual type of the object, using the C++ dynamic_cast or the .NET equivalent keyword, __try_cast. (See Chapter 11 for details on how to use __try_cast.)

    What isn’t obvious from the preceding code is that the enumerator gets a snapshot of the underlying collection. Enumerators are designed for read-only access to collections, and you can have several independent enumerators active on the same collection at one time. If any changes are made to the underlying collection, the snapshot will get out of sync, which causes the IEnumerator to throw an InvalidOperationException to tell you that it no longer reflects the underlying data.

    Note

    Any type that wants to provide enumerator access to its members must implement the IEnumerable interface. This interface has the one method, GetEnumerator, which returns a pointer to some object that implements the IEnumerator interface.




Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
EAN: N/A
Year: 2003
Pages: 208

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net