Bruce has an interesting discussion entitled "Generics Aren't". It's primarily about the new support for generics in Java, but it has a lot of "generic generic" material as well. via [Eric Gunnerson's C# Compendium]
The argument applies to C# generics, but dismisses type-safe data structures as only of concern to collections classes, but that's a narrow view. Using an interface loses type information (pace loose-typing discussion!). Consider the following, in which there's a desire not to allow Cats, Dogs, and Horses to interbreed :
interface BreedingAnimal
{
BreedingAnimal Breed(BreedingAnimal spouse);
}
class Dog: BreedingAnimal
{
public BreedingAnimal Breed(BreedingAnimal spouse)
{
return new Dog();
}
}
class Cat: BreedingAnimal
{
public BreedingAnimal Breed(BreedingAnimal spouse)
{
return new Cat();
}
}
class Horse: BreedingAnimal
{
public BreedingAnimal Breed(BreedingAnimal spouse)
{
return new Horse();
}
}
class TypeSafeBreeder<T> where T:BreedingAnimal
{
public T Reproduce(T aParent, T anotherParent)
{
return (T) aParent.Breed(anotherParent);
}
}
class TypeSafeGenericsAreUseful
{
public static void Main()
{
Dog lassie = new Dog();
Dog rintintin = new Dog();
Cat garfield = new Cat();
TypeSafeBreeder<Dog> kennel = new TypeSafeBreeder<Dog>();
Dog puppy = kennel.Reproduce(lassie, rintintin); //Isn't that nice?
// Dog x = kennel.Reproduce(lassie, garfield); //Won't compile. Isn't that nice?
Horse flicker = (Horse) garfield.Breed(lassie); //<- Compiles clean, runtime error. Darn you, type unsafe code!
}
}
\<
p dir=ltr> (exercise for the reader: as an interface BreedingAnimal.Breed is necessarily public, allowing access to the Breed() method without using a TypeSafeBreeder\<T>. Change the design so that such a threat would only apply to classes in the assembly where these classes are defined.)