Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C# 2008 Step by Step.pdf
Скачиваний:
26
Добавлен:
25.03.2016
Размер:
13.96 Mб
Скачать

302

Part III Creating Components

public int this [int i]

{

get { return this.data[i]; } set { this.data[i] = value; }

}

}

The following code uses the indexer in a similar manner to the property shown earlier:

Wrapper wrap = new Wrapper();

...

int[] myData = new int[2]; myData[0] = wrap[0]; myData[1] = wrap[1]; myData[0]++;

myData[1]++;

This time, incrementing the values in the MyData array has no effect on the original array in the Wrapper object. If you really want to modify the data in the Wrapper

object, you must write statements such as this:

wrap[0]++;

This is much clearer, and safer!

Indexers in Interfaces

You can declare indexers in an interface. To do this, specify the get keyword, the set keyword,

or both, but replace the body of the get or set accessor with a semicolon. Any class or structure that implements the interface must implement the indexer accessors declared in the

interface. For example:

interface IRawInt

{

bool this [ int index ] { get; set; }

}

struct RawInt : IRawInt

{

...

public bool this [ int index ]

{

get { ... } set { ... }

}

...

}

Chapter 16 Using Indexers

303

If you implement the interface indexer in a class, you can declare the indexer implementations as virtual. This allows further derived classes to override the get and set accessors. For example:

class RawInt : IRawInt

{

...

public virtual bool this [ int index ]

{

get { ... } set { ... }

}

...

}

You can also choose to implement an indexer by using the explicit interface implementation syntax covered in Chapter 12, “Working with Inheritance.” An explicit implementation of an indexer is nonpublic and nonvirtual (and so cannot be overridden). For example:

struct RawInt : IRawInt

{

...

bool IRawInt.this [ int index ]

{

get { ... } set { ... }

}

...

}

Using Indexers in a Windows Application

In the following exercise, you will examine a simple phone book application and complete its implementation. You will write two indexers in the PhoneBook class: one that accepts a Name parameter and returns a PhoneNumber and another that accepts a PhoneNumber parameter and returns a Name. (The Name and PhoneNumber structures have already been written.)

You will also need to call these indexers from the correct places in the program.

Familiarize yourself with the application

1.Start Microsoft Visual Studio 2008 if it is not already running.

2.Open the Indexers project, located in the \Microsoft Press\Visual CSharp Step by Step\ Chapter 16\Indexers folder in your Documents folder.

This is a Windows Presentation Foundation (WPF) application that enables a user to search for the telephone number for a contact and also find the name of a contact that matches a given telephone number.

304Part III Creating Components

3.On the Debug menu, click Start Without Debugging.

The project builds and runs. A form appears, displaying two empty text boxes labeled Name and Phone Number. The form also contains three buttons—one to add a name/ phone number pair to a list of names and phone numbers held by the application, one to find a phone number when given a name, and one to find a name when given a phone number. These buttons currently do nothing. Your task is to complete the application so that these buttons work.

4.Close the form, and return to Visual Studio 2008.

5.Display the Name.cs file in the Code and Text Editor window. Examine the Name structure. Its purpose is to act as a holder for names.

The name is provided as a string to the constructor. The name can be retrieved by using the read-only string property named Text. (The Equals and GetHashCode

methods are used for comparing Names when searching through an array of Name values—you can ignore them for now.)

6.Display the PhoneNumber.cs file in the Code and Text Editor window, and examine the PhoneNumber structure. It is similar to the Name structure.

7.Display the PhoneBook.cs file in the Code and Text Editor window, and examine the

PhoneBook class.

This class contains two private arrays: an array of Name values named names, and an array of PhoneNumber values named phoneNumbers. The PhoneBook class also contains an Add method that adds a phone number and name to the phone book. This method is called when the user clicks the Add button on the form. The enlargeIfFull method is called by Add to check whether the arrays are full when the user adds another entry. This method creates two new bigger arrays, copies the contents of the existing arrays to them, and then discards the old arrays.

Write the indexers

1.In the PhoneBook.cs file, add a public read-only indexer to the PhoneBook class, as shown in bold in the following code. The indexer should return a Name and take a PhoneNumber item as its index. Leave the body of the get accessor blank.

The indexer should look like this:

sealed class PhoneBook

{

...

public Name this [PhoneNumber number]

{

get

{

}

}

...

}

Chapter 16 Using Indexers

305

2.Implement the get accessor as shown in bold in the following code. The purpose of

the accessor is to find the name that matches the specifed phone number. To do this, you will need to call the static IndexOf method of the Array class. The IndexOf method

performs a search through an array, returning the index of the first item in the array that matches the specified value. The first argument to IndexOf is the array to search through (phoneNumbers). The second argument to IndexOf is the item you are searching for. IndexOf returns the integer index of the element if it finds it; otherwise, IndexOf returns –1. If the indexer finds the phone number, it should return it; otherwise, it should return an empty Name value. (Note that Name is a structure and will always have a default constructor that sets its private field to null.)

The indexer with its completed get accessor should look like this:

sealed class PhoneBook

{

...

public Name this [PhoneNumber number]

{

get

{

int i = Array.IndexOf(this.phoneNumbers, number); if (i != -1)

return this.names[i];

else

return new Name();

}

}

...

}

3.Add a second public read-only indexer to the PhoneBook class that returns a PhoneNumber and accepts a single Name parameter. Implement this indexer in the same way as the first one. (Again note that PhoneNumber is a structure and therefore always has a default constructor.)

The second indexer should look like this:

sealed class PhoneBook

{

...

public PhoneNumber this [Name name]

{

get

{

int i = Array.IndexOf(this.names, name); if (i != -1)

return this.phoneNumbers[i];

else

return new PhoneNumber();

}

}

...

}

306

Part III Creating Components

Notice that these overloaded indexers can coexist because they return different types, which means that their signatures are different. If the Name and PhoneNumber struc-

tures were replaced by simple strings (which they wrap), the overloads would have the same signature and the class would not compile.

4.On the Build menu, click Build Solution. Correct any syntax errors, and then rebuild if necessary.

Call the indexers

1.Display the Window1.xaml.cs file in the Code and Text Editor window, and then locate the findPhoneClick method.

This method is called when the Search by Name button is clicked. This method is currently empty. Add the code shown in bold in the following example to perform these tasks:

1.1.Read the value of the Text property from the name text box on the form. This is a string containing the contact name that the user has typed in.

1.2.If the string is not empty, search for the phone number corresponding to that name in the PhoneBook by using the indexer. (Notice that the Window1 class contains a private PhoneBook field named phoneBook.) Construct a Name object from the string, and pass it as the parameter to the PhoneBook indexer.

1.3.Write the Text property of the PhoneNumber structure returned by the indexer to the phoneNumber text box on the form.

The findPhoneClick method should look like this:

private void findPhoneClick(object sender, RoutedEventArgs e)

{

string text = name.Text;

if (!String.IsNullOrEmpty(text))

{

phoneNumber.Text = phoneBook[new Name(text)].Text;

}

}

Tip Notice the use of the static String method IsNullOrEmpty to determine whether a string is empty or contains a null value. This is the preferred method for testing whether a string contains a value. It returns true if the string has a value and false otherwise.

2.Locate the findNameClick method in the Window1.xaml.cs file. It is below the

findPhoneClick method.

Chapter 16 Using Indexers

307

The findName_Click method is called when the Search by Phone button is clicked. This method is currently empty, so you need to implement it as follows. (The code is shown in bold in the following example.)

2.1.Read the value of the Text property from the phoneNumber text box on the form. This is a string containing the phone number that the user has typed.

2.2.If the string is not empty, search for the name corresponding to that phone number in the PhoneBook by using the indexer.

2.3.Write the Text property of the Name structure returned by the indexer to the name text box on the form.

The completed method should look like this:

private void findNameClick(object sender, RoutedEventArgs e)

{

string text = phoneNumber.Text; if (!String.IsNullOrEmpty(text))

{

name.Text = phoneBook[new PhoneNumber(text)].Text;

}

}

3. On the Build menu, click Build Solution. Correct any errors that occur.

Run the application

1.On the Debug menu, click Start Without Debugging.

2.Type your name and phone number in the text boxes, and then click Add.

When you click the Add button, the Add method stores the information in the phone book and clears the text boxes so that they are ready to perform a search.

3.Repeat step 2 several times with some different names and phone numbers so that the phone book contains a selection of entries.

Note The application performs no checking of the names and telephone numbers

that you enter, and you can input the same name and telephone number more than once. To avoid confusion, please make sure that you provide different names and telephone numbers.

4.Type a name that you used in step 2 into the Name text box, and then click Search by Name.

The phone number you added for this contact in step 2 is retrieved from the phone book and is displayed in the Phone Number text box.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]