19.1.1 Constraints
Commonly, a generic class will do more than just store data based on a type parameter. Often, the generic class will want to invoke methods on objects whose type is given by a type parameter. For example, an Add method in a Dictionary<K,V> class might need to compare keys using a CompareTo method:
public class Dictionary<K,V>
{
public void Add(K key, V value)
{
...
if (key.CompareTo(x) < 0) {...} // Error, no CompareTo method
...
}
}
Since the type argument specified for K could be any type, the only members that can be assumed to exist on the key parameter are those declared by type object, such as Equals, GetHashCode, and ToString; a compile-time error therefore occurs in the example above. It is of course possible to cast the key parameter to a type that contains a CompareTo method. For example, the key parameter could be cast to IComparable:
public class Dictionary<K,V>
{
public void Add(K key, V value)
{
...
if (((IComparable)key).CompareTo(x) < 0) {...}
...
}
}
While this solution works, it requires a dynamic type check at run-time, which adds overhead. It furthermore defers error reporting to run-time, throwing an InvalidCastException if a key doesn’t implement IComparable.