1.3. Implement the Collection InterfacesIn addition to its generic collection classes, .NET 2.0 also provides a set of generic interfaces that enable you to create type-safe collections that have all the functionality of the earlier, nongeneric .NET 1.x collection types. You'll find these interfaces in the System.Collections.Generic namespace. The namespace also includes a number of related generic interfaces, such as IComparable<T>, which you can use to compare two objects of type T regardless of whether they are part of a collection. You can create a sorted linked list by having each datatype stored in the list implement the IComparable<T> interface and by having your Node object be responsible for inserting each new Node at the correct (sorted) position in the linked list. 1.3.1. How do I do that?Integer already implements IComparable; you can easily modify Pilgrim to do so as well. Modify the definition of the Pilgrim class to indicate that it implements the IComparable<T> interface: public class Pilgrim : IComparable<Pilgrim> Be sure to implement the CompareTo and the Equals methods that the interface requires. The objects these methods receive will be of type Pilgrim because this is a type-safe interface, not a "standard" interface that would pass in objects: public int CompareTo(Pilgrim rhs) All you need to do now is change the logic of adding a node. This time, instead of adding to the end of the list, you'll insert the new node into the list where it belongs based on the implementation of the CompareTo method. Note: You can constrain the datatypes your generic type accepts by using constraints. For this to work, you must ensure that the datatype held in the node implements IComparable. You accomplish this with a constraint using the keyword where: public class Node<T> : IComparable<Node<T>> where T:IComparable<T> This line of code declares a class Node of T that implements IComparable (of Node of T) and that is constrained to hold datatypes that implement IComparable. If you try to have your Node class hold an object that does not implement IComparable, you will receive an error message when you attempt to compile it. You must be careful to return the new head of the list if the new node is "less than" the current head of the list, as shown in Example 1-3 (Changes from the previous example are highlighted.) Example 1-3. Implementing generic interfacesusing System; Output: Adding: 2 8 2 5 1 7 2 8 5 5 1.3.2. What just happened?The Pilgrim class changed just enough to implement the generic IComparable interface. The linked list didn't change at all, but the Node class did undergo some changes to support the sorted list. First, the Node class was marked to implement IComparable and was constrained to hold only objects that themselves implement IComparable: public class Node<T> : IComparable<Node<T>> where T:IComparable<T> Second, Node added a reference to the previous node, in addition to the next node (making this a doubly linked list): private Node<T> next = null; The Node class must implement CompareTo and Equals. These are simple to implement because the constraint ensures that the data you are comparing also implements IComparable: public int CompareTo(Node<T> rhs) 1.3.3. What about . . ....the IComparable requirement? Why did Pilgrim and Node require IComparable, but the linked list did not? To understand this, it's important to note that both Pilgrims and Nodes must be compared; linked lists are not compared. Because the linked list is sorted by sorting its nodes, there is no need to compare two linked lists to see which one is "greater" than the other. ...what about passing generic types to a method; can I do that? Yes, you can pass a generic type to a method, but only if the method is generic. In Example 1-3, you display the contents of the list of integers and the list of pilgrims with the following code: Console.WriteLine("Integers: " + myLinkedList);You are free to create a method to take these lists and display them (or manipulate them): private void DisplayList<T>(string intro, LinkedList When you call the method, you supply the type: DisplayList<int>("Integers", myLinkedList);Tip: The compiler is capable of type inference, so you can rewrite the preceding two lines as follows: DisplayList("Integers", myLinkedList);1.3.4. Where can I learn more?The MSDN Library covers the Generic namespace extensively. Search on Systems.Collections.Generic. Also, see my article on generics on O'Reilly's ONDotnet.com site at http://www.ondotnet.com/pub/a/dotnet/2004/05/17/libertyl. |