The following examples show different ways to initialize jagged arrays. You can initialize jagged arrays by using the following style:
int[][] numbers = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
You can omit the size of the first array, as in the following example:
int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };
Accessing Array Members
Accessing array members in C# is straightforward and similar to how you access array members in C and C++. For example, the following code creates an array called numbers and then assigns 5 to the fifth element of the array:
The following code example shows how to access a member of a jagged array:
int[][] numbers = new int[][]
{
new int[] {1, 2}, new int[] {3, 4}
};
numbers[1][1] = 5;
Arrays Are Objects
Arrays in C# are actually objects. System.Array is the abstract base type of all array types. Therefore, you can use the properties and other class members of
System.Array.
For example, you can use the Length property to get the length of an array. The following code example assigns the length of the numbers array, which is 5, to a variable called LengthOfNumbers:
int[] numbers = {1, 2, 3, 4, 5};
int LengthOfNumbers = numbers.Length;
The System.Array class provides many other useful methods and properties, such as methods for sorting, searching, and copying arrays.
foreach (int i in numbers) foreach (int i in numbers)
{{
}}
*****************************ILLEGAL FOR NON-TRAINER USE******************************
Emphasize the difference between enumeration and an enumerator.
To understand the functionality of the various collection classes, you must understand the key interfaces of the collection classes. A .NET Framework interface provides a way to group a set of related members that can be used to perform a particular action.
For example, a client of an object of any class that implements the IEnumerable interface can obtain an enumerator object for that class. The System.Array class and all of the System.Collections classes support the
IEnumerable interface.
Note It is easy to confuse the term enumerator with enumeration. However, enumerator and enumeration are very different concepts. Enumeration, an enum type in C#, is a distinct type with named constants, as in the following example:
enum Color {Red,Green,Blue}
Support for IEnumerable and the GetEnumerator Method
These classes inherit from IEnumerable and implement its single method GetEnumerator. The GetEnumerator method returns an enumerator that implements the IEnumerator interface.
Enumerators are intended to be used only to read data in the collection. You cannot use enumerators to modify the underlying collection. The enumerator is required to be safe. In other words, enumerators must have a fixed view of the items in a collection that remain the same, even if the collection is modified.
For example, if you call GetEnumerator on a collection at the point in time when the collection contains the elements 1, 2, and 3, the enumerator object that is returned by this method must always produce 1, 2, and 3 when it is iterated over, even if the collection is later changed.
Module 7: Strings, Arrays, and Collections
31
Using Enumerators with Collections
When working with collections, you typically implement an enumerator in one of the following ways:
!The enumerator makes a copy of all of the items in the collection.
Making a copy of a large collection guarantees safety but imposes a severe penalty in performance and memory utilization for large collections and therefore is usually not done.
!The enumerator has a reference to the collection.
If the enumerator implementation uses a reference to the collection, the copy penalty is avoided. However, safety must be guaranteed by another means.
If the collection is static or unchanging, you need take no additional action to ensure safety. The .NET Framework collections are typically not static. Instead, they implement a versioning mechanism. Every time a .NET Framework collection changes, the collection’s version number is incremented. An enumerator that detects that the collection’s version number has changed after the enumerator was created throws an InvalidOperationException that should be caught and handled by the enumerator’s client.
The IEnumerator interface has the Current public instance property. The
Current property gets the current element in the collection.
An enumerator maintains a reference to the item in the collection that is currently being enumerated. The enumerator is in an invalid state if it is positioned before the first element in the collection or after the last element in the collection. When the enumerator is in an invalid state, calling Current throws an exception.
The IEnumerator interface also requires the following public instance methods.
Method
Use
MoveNext
Advances the enumerator to the next element of the collection.
Reset
Sets the enumerator to its initial position, which is before the first
element in the collection.
Initially, the enumerator is positioned before the first element in the collection. Reset also brings the enumerator back to this position. Therefore, after an enumerator is created or after a Reset, you must call MoveNext to advance the enumerator to the first element of the collection before reading the value of
Current.
Current returns the same object until MoveNext or Reset is called.
After the end of the collection is passed, the enumerator returns to an invalid state. At this time, calling MoveNext returns false. Calling Current throws an exception if the last call to MoveNext returned false.
32
Module 7: Strings, Arrays, and Collections
The following code example shows how to iterate over a collection. In this example, the collection is an instance of System.Array.
int[] numbers = new int[5] {1, 2, 3, 4, 5}; IEnumerator e = numbers.GetEnumerator(); while (e.MoveNext()) {
Console.WriteLine("Number: {0}", (int)e.Current);
}
This code outputs:
Number: 1
Number: 2
Number: 3
Number: 4
Number: 5
Using foreach to Iterate Through an Array
C# provides the foreach statement, which is a less verbose way to iterate through the elements of an array. For example, the following code example creates an array called numbers and iterates through it with the foreach statement:
int[] numbers = {4, 5, 6, 1, 2, 3, -2, -1, 0}; foreach (int i in numbers) {
System.Console.WriteLine("Number: {0}", i);
}
Module 7: Strings, Arrays, and Collections
33
Comparing
Topic Objective
To explain how the
IComparer and
IComparable interfaces are used to sort and order a collection’s items.
Lead-in
To sort a collection, you must be able to compare and order the items of the collection.
!To Sort and Search, Collections Must Be Able to Compare Items
!IComparer’s Compare Method Compares Two Objects of Any Type
int Compare( object x, object y ); int Compare( object x, object y );
#Comparer class is the default implementation of IComparer
Its Compare method uses IComparable.CompareTo
!IComparable’s CompareTo Method Compares the Current Instance to an Object of the Same Type
int CompareTo( object anObject ); int CompareTo( object anObject );
! CompareTo Returns
Value
Meaning
Less than zero
Instance is less than object
Zero
Instance is equal to object
Greater than zero
Instance is greater than object
*****************************ILLEGAL FOR NON-TRAINER USE******************************
To sort a collection, you must be able to compare and order the items of the collection. The IComparer and IComparable interfaces are used to sort and order a collection’s items.
The IComparer interface’s Compare method compares two objects of any type and returns a value that indicates whether one object is less than, equal to, or greater than the other.
The Compare method provides the sort order of a collection and is also used in conjunction with the Array.BinarySearch method.
Default Implementation of IComparer
The Comparer class provides the default implementation of the IComparer interface.
The Comparer class’s Compare(object a, object b) method is implemented as follows:
!If a implements IComparable, then a.CompareTo(b) is returned.
!Otherwise, if b implements IComparable, then b.CompareTo(a) is returned.
The IComparable interface has a single CompareTo method that compares the current instance with another object of the same type.
34
Module 7: Strings, Arrays, and Collections
Return Values of CompareTo
The value returned by the CompareTo method is a 32-bit signed integer that indicates the relative order of the instance and the object that is passed as a parameter, as in the following example:
int CompareTo(object anObject);
The following table describes the possible meanings of the return value.
Value
Meaning
Less than zero
This instance is less than anObject.
Zero
This instance is equal to anObject.
Greater than zero
This instance is greater than anObject.
By definition, any object compares greater than a null reference, and two null references compare equal to each other.
Issues with Using IComparable.CompareTo
The parameter, anObject, must be the same type as the class or value type that implements this interface. Otherwise, ArgumentException is thrown.
The default comparison procedures use the Thread.CurrentCulture of the current thread unless it is otherwise specified. String comparisons may have different results depending on the culture.
To perform case-insensitive comparisons on strings, you can use the
CaseInsensitiveComparer class’s implementation of the IComparer interface.
Module 7: Strings, Arrays, and Collections
35
Sorting
Topic Objective
To explain how to compare and order the items of a collection by using the
IComparer and IComparable interfaces. Knowledge of this topic is required for the lab.
Lead-in
Some collections, such as Array, sort their items when their Sort method is called.
! Sort Method Using Element’s IComparable.CompareTo
Array.Sort( anArray );
Array.Sort( anArray );
! IComparable.CompareTo Design Pattern
public int CompareTo(Object anObject) { public int CompareTo(Object anObject) {
if ( anObject == null) return 1; if ( anObject == null) return 1; if ( !(anObject is <classname>) ) {
if ( !(anObject is <classname>) ) { throw new ArgumentException(); } throw new ArgumentException(); }
// Do comparison and return a // Do comparison and return a
// negative integer if instance < anObject // negative integer if instance < anObject // 0 if instance == anObject
// 0 if instance == anObject
}}
// positive integer if instance > anObject // positive integer if instance > anObject
*****************************ILLEGAL FOR NON-TRAINER USE******************************
Some collections, such as Array, sort their items when their Sort method is called. Overloaded versions of the Sort method allow you to supply an IComparer implementation in the method call that is used to perform the ordering of the elements. These overloaded versions of the Sort method provide you with the flexibility to resort the same collection of items by using different IComparer implementations.
If you use the array’s public static void Sort(Array) method, the default Comparer class implementation of IComparer is used, and the array’s elements are sorted by using the elements’ implementation of the CompareTo method of the IComparable interface.
Other collection classes, such as SortedList, have constructors whose parameters determine the sort order. These classes are less flexible than classes that implement a sort method because after they are constructed their sort ordering cannot be changed.
36
Module 7: Strings, Arrays, and Collections
Demonstration: Sorting and Enumerating an Array
Topic Objective
To demonstrate how to sort and enumerate an array.
Lead-in
In this demonstration, we will sort an array by using the CompareTo method when the value type or class of the items in the collection implements the
IComparable interface.
*****************************ILLEGAL FOR NON-TRAINER USE******************************
For Your Information
You should carefully cover the CompareTo method because it is used in the lab.
As stated in Sorting in this module, you can sort an array by using the CompareTo method when the value type or class of the items in the collection implements the IComparable interface.
In this demonstration, an Employee class contains an employee’s name, level number, and hiring date. To sort an array of Employees based on increasing level numbers where equal level numbers are then ordered by increasing hiring date, implement the following: