Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#

.pdf
Скачиваний:
173
Добавлен:
12.02.2016
Размер:
16.87 Mб
Скачать

Module 7: Strings, Arrays, and Collections

29

 

 

 

Jagged Array (Array-of-Arrays)

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:

int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; numbers[4] = 5;

The following code example declares a multidimensional array and assigns 5 to the member located at [1, 1]:

int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} }; numbers[1, 1] = 5;

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.

Console.WriteLine("Number: {0}", i); Console.WriteLine("Number: {0}", i);

30

Module 7: Strings, Arrays, and Collections

Iterating Over

Topic Objective

To explain the role of the

IEnumerable and

IEnumerator interfaces in collections.

Lead-in

A .NET Framework interface provides a way to group a set of related members that can be used to perform a particular action.

!System.Array and System.Collections Classes Implement IEnumerable Interface and its GetEnumerator Method

!Enumerator Classes Implement IEnumerator

# Members: MoveNext, Reset, and Current

int[] numbers = new int[5] {1, 2, 3, 4, 5}; int[] numbers = new int[5] {1, 2, 3, 4, 5}; IEnumerator e = numbers.GetEnumerator(); IEnumerator e = numbers.GetEnumerator(); while (e.MoveNext()) {

while (e.MoveNext()) {

}}

Console.WriteLine("Number: {0}", (int)e.Current); Console.WriteLine("Number: {0}", (int)e.Current);

// alternatively // alternatively

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:

using System;

namespace ArraySorting

{

public class Employee : IComparable

{

public string name; public int level;

public DateTime hiringDate;

public Employee(

string name,int level,DateTime hiringDate) { this.name = name;

this.level=level;

this.hiringDate=hiringDate;

}

public int CompareTo(Object anObject) { if (anObject == null) return 1;

if ( !(anObject is Employee) ) { throw new ArgumentException();

}

(Code continued on the following page.)

Module 7: Strings, Arrays, and Collections

37

 

 

 

Employee anEmployee = (Employee)anObject; if ( level < anEmployee.level ) return -1; else {

if ( level == anEmployee.level ) { if (hiringDate < anEmployee.hiringDate)

return -1; else {

if ( hiringDate == anEmployee.hiringDate)

return 0; else return 1;

}

}

else return 1;

}

}

}

public class ArraySort {

public static void Main() {

//Create and initialize a new Array instance. Employee[] myEmployees = new Employee[10]; myEmployees[0] = new Employee(

"a",2,new DateTime(1990,1,1)); myEmployees[1] = new Employee(

"b",2,new DateTime(2000,1,1)); myEmployees[2] = new Employee(

"c",2,new DateTime(1990,1,1)); myEmployees[3] = new Employee(

"d",4,new DateTime(2000,1,1)); myEmployees[4] = new Employee(

"e",4,new DateTime(1990,1,1)); myEmployees[5] = new Employee(

"f",4,new DateTime(2000,1,1)); myEmployees[6] = new Employee(

"g",1,new DateTime(1990,2,5)); myEmployees[7] = new Employee(

"h",1,new DateTime(2000,1,1)); myEmployees[8] = new Employee(

"i",1,new DateTime(1990,1,1)); myEmployees[9] = new Employee(

"j",0,new DateTime(2001,1,1));

//Display the values of the Array. Console.WriteLine(

"The Array instance initially contains values:" );

PrintIndexAndValues( myEmployees );

// Sort the values of the Array. Array.Sort( myEmployees );

(Code continued the following page.)

38Module 7: Strings, Arrays, and Collections

//Display the values of the Array.

Console.WriteLine( "After sorting:" ); PrintIndexAndValues( myEmployees );

}

public static void PrintIndexAndValues( Array myEmployees ) {

foreach ( Employee e in myEmployees ) { Console.WriteLine(

"name: {0} \tlevel: {1} \tdate:{2:d}", e.name, e.level, e.hiringDate);

}

}

}

}

The preceding code displays the following output to the console:

The Array instance initially contains values:

name: a

level: 2

date:1/1/1990

name: b

level: 2

date:1/1/2000

name: c

level: 2

date:1/1/1990

name: d

level: 4

date:1/1/2000

name: e

level: 4

date:1/1/1990

name: f

level: 4

date:1/1/2000

name: g

level: 1

date:2/5/1990

name: h

level: 1

date:1/1/2000

name: i

level: 1

date:1/1/1990

name: j

level: 0

date:1/1/2001

After sorting:

 

 

name: j

level: 0

date:1/1/2001

name: i

level: 1

date:1/1/1990

name: g

level: 1

date:2/5/1990

name: h

level: 1

date:1/1/2000

name: c

level: 2

date:1/1/1990

name: a

level: 2

date:1/1/1990

name: b

level: 2

date:1/1/2000

name: e

level: 4

date:1/1/1990

name: d

level: 4

date:1/1/2000

name: f

level: 4

date:1/1/2000

Соседние файлы в папке c#