Constraints

There are times when you must ensure that the elements you add to a generic list meet certain constraints (e.g., they derive from a given base class, or they implement a specific interface). In the next example, you implement a simplified, singly linked, sortable list. The list consists of Nodes, and each Node must be guaranteed that the types added to it implement IComparer. You do so with the following statement:

 public class Node<T> :IComparable<Node<T>> where T : IComparable<T>

This defines a generic Node that holds a type, T. Node of T implements the IComparable<T> interface, which means that two Nodes of T can be compared. The Node class is constrained (where T : IComparable<T>) to hold only types that implement the IComparable interface. Thus, you may substitute any type for T as long as that type implements IComparable.

Example 9-12 illustrates the complete implementation, with analysis to follow.

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; } // implement the interface public int CompareTo(Employee rhs) { return this.name.CompareTo(rhs.name); } public bool Equals(Employee rhs) { return this.name == rhs.name; } } // node must implement IComparable of Node of T. // constrain Nodes to only take items that implement IComparable // ...

Get Programming C# 3.0, 5th Edition now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.