9.5 constraints
Sometimes you have to make sure that elements added to the generic list have certain constraints (for example, they inherit from a given base class or that they implement the specified interface). In the example below, we have implemented a simple, sortable list of single linked lists. The linked list consists of multiple node, each node must ensure that the elements added to implement the IComparer interface. You can declare this:
public class node<t>: icomparable<node<t>> where t:icomparable<t>
This code defines a generic node, which operates the type T. The T in node implements the Icomparable<t> interface, which means that two node's t can be compared. The node class uses constraints (where t:icomparable<t>) to manipulate the types that implement the IComparable interface. So you can use any type to replace T, as long as that type implements the IComparable interface
Example 9-12 illustrates the complete interface implementation and analyzes the following.
Example 9-12 using constraints
using System;
using System.Collections.Generic;
namespace Usingconstraints
{
public class employee:icomparable<employee>
{
private string name;
public Employee (string name)
{
this.name = name;
}
public override string ToString ()
{
return this.name;
}
//Implementation Interface
public int CompareTo (Employee rhs)
{
return This.name.CompareTo (rhs.name);
}
public bool Equals (Employee RHS)
{
return this.name = = Rhs.name;
}
}
The
//node must implement the Node<t> IComparable interface.
//through the WHERE Keyword constraint node receives only the items that implement the IComparable interface
public class node<t>: icomparable<node<t>> where t:icomparable<t>
{
//Member variable
private T data;
private node<t> next = null; Next node
private node<t> prev = null; Previous Node
//Construction method
public Node (T data)
{
this.data = data;
}
Attribute
Public T Data
{
get {return this.data;}
}
Public node<t> Next
{
get {return this.next;}
}
public int CompareTo (node<t> rhs)
{//This is used because of constraints
return Data.compareto (Rhs.data);
}
public bool Equals (node<t> RHS)
{
return This.data.Equals (Rhs.data);
}
//Method
public node<t> Add (node<t> newNode)
{//below "I" represents the current instance of the class
if (This.compareto (NewNode) > 0)//less than I put it in front of me
{
Newnode.next = this; The next node of the new node points to me
//If I have the previous node, the previous node of the new node points to it
//New node as its next node
if (This.prev!= null)
{
this.prev.next = NewNode;
Newnode.prev = This.prev;
}
//Set my previous node to be a new node
This.prev = NewNode;
//From the following linkedlist<t> code can be learned that the addition is from
The
//Header node begins to judge that it is only returned when the new node is the head node
return newNode;
}
else//greater than = I put it behind me
{
//If I have the next one, compare it to the next
//Here recursion is used until the new node finds a node larger than it
if (this.next!= null)
{
This.next.Add (NewNode);
}
//If I don't have the next node, set the new node for my next
//node and point its last node to me
Else
{
this.next = NewNode;
Newnode.prev = this;
}
return to this;
}
}
public override string ToString ()
{
string output = data. ToString ();
if (next!= null)
{//This also uses all the elements on the recursive print List
output = "," + next. ToString ();
}
return output;
}
}
public class linkedlist<t> where t:icomparable<t>
{
//Member variable
private node<t> headnode = null;
//Indexer
public T This[int index]
{
Get
{//Because it is a linked list, it needs to be traversed from the beginning
int ctr = 0;
node<t> Node = Headnode;
while (node!= null && CTR <= Index)
{
if (ctr = = index)
{
return node. Data;
}
Else
{
node = node. Next;
}
++ctr;
}
throw new ArgumentOutOfRangeException ();
}
}
//Default construction method
public LinkedList ()
{
}
//Method
public void Add (T data)
{
if (Headnode = null)
{
Headnode = new node<t> (data);
}
Else
{
Headnode = Headnode.add (new node<t> (data));
}
}
public override string ToString ()
{
if (this.headnode!= null)
{
return this.headNode.ToString ();
}
Else
{
return string. Empty;
}
}
}
//Test class
class Test
{
static void Main ()
{///create an instance to perform the method
Test t = new Test ();
T.run ();
}
public void Run ()
{
linkedlist<int> mylinkedlist = new linkedlist<int> ();
Random rand = new Random ();
Console.Write ("adding:");
for (int i = 0; i < i++)
{
int nextint = rand. Next (10);
Console.Write ("{0}", Nextint);
Mylinkedlist.add (Nextint);
}
linkedlist<employee> employees = new linkedlist<employee> ();
employees. ADD (New Employee ("John"));
employees. ADD (New Employee ("Paul"));
employees. ADD (New Employee ("George"));
employees. ADD (New Employee ("Ringo"));
Console.WriteLine ("\nretrieving collections");
Console.WriteLine ("Integers:" + mylinkedlist);
Console.WriteLine ("Employees:" + Employees);
}
}
}