An OO language lets us use an object of child class C in any context that expects an object of parent class P. This is OO subtyping. Now suppose we have a class Container. Is Container a subtype of Container

? Or perhaps Container

is a subtype of Container? Or maybe neither is a subtype of the other? This is the issue of _conformance_. A hash table needs T to have a hash function. A commerce scheduling system may need to be able to create new shipping orders (e.g., for UPS, FedEx, DHL, or USPost). Suppose the constructor for my hash table expects a 'hasher' for T interface Hasher { int hash(T t); } class HashTable { Hasher hf; // hash function public HashTable(Hasher h) { hf = h; } Here T is the type in the hash table. It is passed _in_ to the hash method. and the constructor for my scheduling system expects a 'shipper' for T: interface Shipper { O create(...); } class Scheduler { Shipper sf; // shipping order factory public Scheduler(Shipper s) { sf = s; } Here O is the shipping order to be scheduled. It is passed _out_ of the create method. The hash table will be happy with anything that can hash a T. It will be happy if I give it a Hasher that can hash some superclass of T. The scheduler will be happy with anything that can generate an O. It will be happy if I give it a Shipper that can generate a subclass of O. In Java we specify this with type wild cards: The constructor parameter types and save-it fields of the class are labeled and respectively. In effect, the hash table is promising never to try to pull a T object out of a method of Hasher (and the compiler checks). The scheduler is promising never to try to pass an O object into a method of Shipper (and the compiler checks). C# simplifies (and restricts) all this. Instead of labeling the constructor parameter and the save-it fields, we label the interface: interface Hasher { int hash(T t); } interface Shipper { O create(...); } In Java you could use an interface with methods that pass in and others that pass out as either a Hasher or a Shipper, so long as you only used the methods that go the "right way" according to your super or extends label. In C# you can't mix and match this way. The Hasher is _contravariant_ in T: T is an X means Hasher is a Hasher The Shipper is _covariant_ in O: X is an O means Shipper is a Shipper