Tải bản đầy đủ - 0 (trang)
13-3. Implement a Comparable Type

13-3. Implement a Comparable Type

Tải bản đầy đủ - 0trang

CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



The Code

The Newspaper class listed here demonstrates the implementation of both the IComparable and IComparer

interfaces. The Newspaper.CompareTo method performs a case-insensitive comparison of two Newspaper

objects based on their name fields. A private nested class named AscendingCirculationComparer

implements IComparer and compares two Newspaper objects based on their circulation fields. An

AscendingCirculationComparer object is obtained using the static Newspaper.CirculationSorter

property.

The Main method shown here demonstrates the comparison and sorting capabilities provided by

implementing the IComparable and IComparer interfaces. The method creates a System.Collections.

ArrayList collection containing five Newspaper objects. Main then sorts the ArrayList twice using the

ArrayList.Sort method. The first Sort operation uses the default Newspaper comparison mechanism

provided by the IComparable.CompareTo method. The second Sort operation uses an

AscendingCirculationComparer object to perform comparisons through its implementation

of the IComparer.Compare method.

using System;

using System.Collections.Generic;

namespace Apress.VisualCSharpRecipes.Chapter13

{

public class Newspaper : IComparable

{

private string name;

private int circulation;

private class AscendingCirculationComparer : IComparer

{

// Implementation of IComparer.Compare. The generic definition of

// IComparer allows us to ensure both arguments are Newspaper

// objects.

public int Compare(Newspaper x, Newspaper y)

{

// Handle logic for null reference as dictated by the

// IComparer interface. Null is considered less than

// any other value.

if (x == null && y == null) return 0;

else if (x == null) return -1;

else if (y == null) return 1;

// Short-circuit condition where x and y are references

// to the same object.

if (x == y) return 0;

// Compare the

//

return

//

return

//

return



circulation figures. IComparer dictates that:

less than zero if x < y

zero if x = y

greater than zero if x > y



632



www.it-ebooks.info



CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



// This logic is easily implemented using integer arithmetic.

return x.circulation - y.circulation;

}

}

// Simple Newspaper constructor.

public Newspaper(string name, int circulation)

{

this.name = name;

this.circulation = circulation;

}

// Declare a read-only property that returns an instance of the

// AscendingCirculationComparer.

public static IComparer CirculationSorter

{

get { return new AscendingCirculationComparer(); }

}

// Override Object.ToString.

public override string ToString()

{

return string.Format("{0}: Circulation = {1}", name, circulation);

}

// Implementation of IComparable.CompareTo. The generic definition

// of IComparable allows us to ensure that the argument provided

// must be a Newspaper object. Comparison is based on a

// case-insensitive comparison of the Newspaper names.

public int CompareTo(Newspaper other)

{

// IComparable dictates that an object is always considered greater

// than null.

if (other == null) return 1;

// Short-circuit the case where the other Newspaper object is a

// reference to this one.

if (other == this) return 0;

// Calculate return value by performing a case-insensitive

// comparison of the Newspaper names.

// Because the Newspaper name is a string, the easiest approach

// is to rely on the comparison capabilities of the String

// class, which perform culture-sensitive string comparisons.

return string.Compare(this.name, other.name, true);

}

}



633



www.it-ebooks.info



CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



// A class to demonstrate the use of Newspaper.

public class Recipe13_03

{

public static void Main()

{

List newspapers = new List();

newspapers.Add(new

newspapers.Add(new

newspapers.Add(new

newspapers.Add(new

newspapers.Add(new



Newspaper("The

Newspaper("The

Newspaper("The

Newspaper("The

Newspaper("The



Echo", 125780));

Times", 55230));

Gazette", 235950));

Sun", 88760));

Herald", 5670));



Console.Clear();

Console.WriteLine("Unsorted newspaper list:");

foreach (Newspaper n in newspapers)

{

Console.WriteLine(" " + n);

}

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Newspaper list sorted by name (default order):");

newspapers.Sort();

foreach (Newspaper n in newspapers)

{

Console.WriteLine(" " + n);

}

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Newspaper list sorted by circulation:");

newspapers.Sort(Newspaper.CirculationSorter);

foreach (Newspaper n in newspapers)

{

Console.WriteLine(" " + n);

}

// Wait to continue.

Console.WriteLine(Environment.NewLine);

Console.WriteLine("Main method complete. Press Enter");

Console.ReadLine();

}

}

}



Usage

Running the example will produce the results shown here. The first list of newspapers is unsorted, the

second is sorted using the IComparable interface, and the third is sorted using a comparer class that

implements IComparer.



634



www.it-ebooks.info



CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



Unsorted newspaper list:

The Echo: Circulation = 125780

The Times: Circulation = 55230

The Gazette: Circulation = 235950

The Sun: Circulation = 88760

The Herald: Circulation = 5670



Newspaper list sorted by name (default order):

The Echo: Circulation = 125780

The Gazette: Circulation = 235950

The Herald: Circulation = 5670

The Sun: Circulation = 88760

The Times: Circulation = 55230



Newspaper list sorted by circulation:

The Herald: Circulation = 5670

The Times: Circulation = 55230

The Sun: Circulation = 88760

The Echo: Circulation = 125780

The Gazette: Circulation = 235950



635



www.it-ebooks.info



CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



13-4. Implement an Enumerable Collection

Problem

You need to create a collection type whose contents you can enumerate using a foreach statement.



Solution

Implement the generic interface System.Collections.Generic.IEnumerable on your collection type.

The GetEnumerator method of the IEnumerable interface returns an enumerator, which is an object that

implements the interface System.Collections.Generic.IEnumerator. Within the GetEnumerator

method, traverse the items in the collection using whatever logic is appropriate to your data structure

and return the next value using the yield return statement. The C# compiler will automatically generate

the necessary code to enable enumeration across the contents of your type.



How It Works

A numeric indexer allows you to iterate through the elements of most standard collections using a for

loop. However, this technique does not always provide an appropriate abstraction for nonlinear data

structures, such as trees and multidimensional collections. The foreach statement provides an easy-touse and syntactically elegant mechanism for iterating through a collection of objects, regardless of their

internal structures.

In order to support foreach semantics, the type containing the collection of objects should

implement the IEnumerable interface. The IEnumerable interface declares a single method named

GetEnumerator, which takes no arguments and returns an object that implements IEnumerator. All

you need to do in your GetEnumerator method is write the code necessary to iterate through the items in

your collection using logic appropriate to the data structure. Each time you want to return an item, call

the yield return statement and specify the value to return. The compiler generates code that returns

the specified value and maintains appropriate state for the next time a value is requested. If you need to

stop partway through the enumeration, call the yield break statement instead, and the enumeration

will terminate as if it had reached the end of the collection.



■ Tip You do not actually need to explicitly implement IEnumerable on your type to make it enumerable. As long

as it has a GetEnumerator method that returns an IEnumerator instance, the compiler will allow you to use the

type in a foreach statement. However, it is always good practice to explicitly declare the capabilities of a type by

declaring the interfaces it implements, as it allows users of your class to more easily understand its capabilities

and purpose.



The GetEnumerator method is used automatically whenever you use an instance of your collection

type in a foreach statement. However, if you want to provide multiple ways to enumerate the items in

your collection, you can implement multiple methods or properties that are declared to return



636



www.it-ebooks.info



CHAPTER 13 ■ COMMONLY USED INTERFACES AND PATTERNS



IEnumerable instances. Within the body of the member, use the yield return statement just

mentioned, and the C# compiler will generate the appropriate code automatically. To use one of the

alternative enumerations from a foreach statement, you must directly reference the appropriate

member, as in this example:

foreach (node n in Tree.BreadthFirst)



The Code

The following example demonstrates the creation of an enumerable collection using the IEnumerable

and IEnumerator interfaces in conjunction with the yield return and yield break statements. The

Team class, which represents a team of people, is a collection of enumerable TeamMember objects.

using System;

using System.Collections.Generic;

namespace Apress.VisualCSharpRecipes.Chapter13

{

// The TeamMember class represents an individual team member.

public class TeamMember

{

public string Name;

public string Title;

// Simple TeamMember constructor.

public TeamMember(string name, string title)

{

Name = name;

Title = title;

}

// Returns a string representation of the TeamMember.

public override string ToString()

{

return string.Format("{0} ({1})", Name, Title);

}

}

// Team class represents a collection of TeamMember objects.

public class Team

{

// A List to contain the TeamMember objects.

private List teamMembers = new List();



637



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

13-3. Implement a Comparable Type

Tải bản đầy đủ ngay(0 tr)

×