Class Array and Enumerators

Chapter 8 presented basic array-processing capabilities. All arrays implicitly inherit from abstract base class Array (namespace System), which defines property Length, which specifies the number of elements in the array. In addition, class Array provides static methods that provide algorithms for processing arrays. Typically, class Array overloads these methodsfor example, Array method Reverse can reverse the order of the elements in an entire array or can reverse the elements in a specified range of elements in an array. For a complete list of class Array's static methods visit:

msdn2.microsoft.com/en-us/library/system.array.aspx

Figure 27.3 demonstrates several static methods of class Array.

Figure 27.3. Array class used to perform common array manipulations.

1 // Fig. 27.3: UsingArray.cs 2 // Array class static methods for common array manipulations. 3 using System; 4 using System.Collections; 5 6 // demonstrate algorithms of class Array 7 public class UsingArray 8 { 9 private static int[] intValues = { 1, 2, 3, 4, 5, 6 }; 10 private static double[] doubleValues = { 8.4, 9.3, 0.2, 7.9, 3.4 }; 11 private static int[] intValuesCopy; 12 13 // method Main demonstrates class Array's methods 14 public static void Main( string[] args ) 15 { 16 intValuesCopy = new int[ intValues.Length ]; // defaults to zeroes 17 18 Console.WriteLine( "Initial array values: " ); 19 PrintArrays(); // output initial array contents 20 21 // sort doubleValues 22 Array.Sort( doubleValues ); 23 24 // copy intValues into intValuesCopy 25 Array.Copy( intValues, intValuesCopy, intValues.Length ); 26 27 Console.WriteLine( " Array values after Sort and Copy: " ); 28 PrintArrays(); // output array contents 29 Console.WriteLine(); 30 31 // search for 5 in intValues 32 int result = Array.BinarySearch( intValues, 5 ); 33 if ( result >= 0 ) 34 Console.WriteLine( "5 found at element {0} in intValues", 35 result ); 36 else 37 Console.WriteLine( "5 not found in intValues" ); 38 39 // search for 8763 in intValues 40 result = Array.BinarySearch( intValues, 8763 ); 41 if ( result >= 0 ) 42 Console.WriteLine( "8763 found at element {0} in intValues", 43 result ); 44 else 45 Console.WriteLine( "8763 not found in intValues" ); 46 } // end method Main 47 48 // output array content with enumerators 49 private static void PrintArrays() 50 { 51 Console.Write( "doubleValues: " ); 52 53 // iterate through the double array with an enumerator 54 IEnumerator enumerator = doubleValues.GetEnumerator(); 55 56 while ( enumerator.MoveNext() ) 57 Console.Write( enumerator.Current + " " ); 58 59 Console.Write( " intValues: " ); 60 61 // iterate through the int array with an enumerator 62 enumerator = intValues.GetEnumerator(); 63 64 while ( enumerator.MoveNext() ) 65 Console.Write( enumerator.Current + " " ); 66 67 Console.Write( " intValuesCopy: " ); 68 69 // iterate through the second int array with a foreach statement 70 foreach ( int element in intValuesCopy ) 71 Console.Write( element + " " ); 72 73 Console.WriteLine(); 74 } // end method PrintArrays 75 } // end class UsingArray

Initial array values: doubleValues: 8.4 9.3 0.2 7.9 3.4 intValues: 1 2 3 4 5 6 intValuesCopy: 0 0 0 0 0 0 Array values after Sort and Copy: doubleValues: 0.2 3.4 7.9 8.4 9.3 intValues: 1 2 3 4 5 6 intValuesCopy: 1 2 3 4 5 6 5 found at element 4 in intValues 8763 not found in intValues

The using directives in lines 34 include the namespaces System (for classes Array and Console) and System.Collections (for interface IEnumerator, which we discuss shortly). References to the assemblies for these namespaces are implicitly included in every application, so we do not need to add any new references to the project file.

Our test class declares three static array variables (lines 911). The first two lines initialize intValues and doubleValues to an int and double array, respectively. Static variable intValuesCopy is intended to demonstrate the Array's Copy method, so it is left with the default value nullit does not yet refer to an array.

Line 16 initializes intValuesCopy to an int array with the same length as array intValues. Line 19 calls the PrintArrays method (lines 4974) to output the initial contents of all three arrays. We discuss the PrintArrays method shortly. We can see from the output of Fig. 27.3 that each element of array intValuesCopy is initialized to the default value 0.

Line 22 uses static Array method Sort to sort array doubleValues. When this method returns, the array contains its original elements sorted in ascending order.

Line 25 uses static Array method Copy to copy elements from array intValues to array intValuesCopy. The first argument is the array to copy (intValues), the second argument is the destination array (intValuesCopy) and the third argument is an int representing the number of elements to copy (in this case, intValues.Length specifies all elements).

Lines 32 and 40 invoke static Array method BinarySearch to perform binary searches on array intValues. Method BinarySearch receives the sorted array in which to search and the key for which to search. The method returns the index in the array at which it finds the key (or a negative number if the key was not found). Notice that BinarySearch assumes that it receives a sorted array. Its behavior on an unsorted array is unpredictable. Chapter 24, Searching and Sorting, discusses binary searching in detail.

Common Programming Error 27 1

Passing an unsorted array to BinarySearch is a logic errorthe value returned is undefined.

The PrintArrays method (lines 4974) uses class Array's methods to loop though each array. In line 54, the GetEnumerator method obtains an enumerator for array intValues. Recall that Array implements the IEnumerable interface. All arrays inherit implicitly from Array, so both the int[] and double[] array types implement IEnumerable interface method GetEnumerator, which returns an enumerator that can iterate over the collection. Interface IEnumerator (which all enumerators implement) defines methods MoveNext and Reset and property Current. MoveNext moves the enumerator to the next element in the collection. The first call to MoveNext positions the enumerator at the first element of the collection. MoveNext returns TRue if there is at least one more element in the collection; otherwise, the method returns false. Method Reset positions the enumerator before the first element of the collection. Methods MoveNext and Reset throw an InvalidOperationException if the contents of the collection are modified in any way after the enumerator is created. Property Current returns the object at the current location in the collection.

Common Programming Error 27 2

If a collection is modified after an enumerator is created for that collection, the enumerator immediately becomes invalidany methods called with the enumerator after this point throw InvalidOperationExceptions. For this reason, enumerators are said to be "fail fast."

When an enumerator is returned by the GetEnumerator method in line 54, it is initially positioned before the first element in Array doubleValues. Then when line 56 calls MoveNext in the first iteration of the while loop, the enumerator advances to the first element in doubleValues. The while statement in lines 5657 loops over each element until the enumerator passes the end of doubleValues and MoveNext returns false. In each iteration, we use the enumerator's Current property to obtain and output the current array element. Lines 6265 iterate over array intValues.

Notice that PrintArrays is called twice (lines 19 and 28), so GetEnumerator is called twice on doubleValues. The GetEnumerator method (lines 54 and 62) always returns an enumerator positioned before the first element. Also notice that the IEnumerator property Current is read-only. Enumerators cannot be used to modify the contents of collections, only to obtain the contents.

Lines 7071 use a foreach statement to iterate over the collection elements like an enumerator. In fact, the foreach statement behaves exactly like an enumerator. Both loop over the elements of an array one-by-one in a well-defined order. Neither allows you to modify the elements during the iteration. This is not a coincidence. The foreach statement implicitly obtains an enumerator via the GetEnumerator method and uses the enumerator's MoveNext method and Current property to traverse the collection, just as we did explicitly in lines 5457. For this reason, we can use the foreach statement to iterate over any collection that implements the IEnumerable interfacenot just arrays. We demonstrate this functionality in the next section when we discuss class ArrayList.

Other staticArray methods include Clear (to set a range of elements to 0 or null), CreateInstance (to create a new array of a specified type), IndexOf (to locate the first occurrence of an object in an array or portion of an array), LastIndexOf (to locate the last occurrence of an object in an array or portion of an array) and Reverse (to reverse the contents of an array or portion of an array).

Non Generic Collections

Категории