The way generics are implemented in .NET requires that all Foo<T>
must behave largely the same way regardless of T
. Among other things, all Foo<T>
must have the same members, save only for the fact that members may include T
in their definitions. If Foo<T>
could inherit from T
, knowing what members Foo<T>
exposed would require knowing what members T
exposed, which could of course be completely different for a Foo<Automobile>
and a Foo<Cat>
. If one knows that Foo<T>
will only be used for types that derive from e.g. Animal
, one could define a class Foo<T> : Animal where T:Animal
, but that would only allow a Foo<Cat>
to be used as an Animal
--not as a Cat
.
In many cases, however, what is really needed is not a type Foo<T>
which actually inherits T
, but rather the ability to create an object which mostly behaves like T
, but with some differences. The .NET Framework doesn't allow that to be done directly either, but there are some libraries which can auto-generate proxy objects for that purpose. Given an interface and one or more objects, each of which implements some interface members, and which collectively implement all of them, a proxy generator will create (at run time!) a new class which holds references to the supplied objects and implements that interface by creating for each interface method a class method that chains to the corresponding method on one of the passed-in objects.
Note that although the method which creates these new classes will be generic, the classes themselves will not be. It may be that myProxyMaker.Create<IFoo>(IFlyingMammal)
returns a proxy8675309
and a myProxyMaker.Create<ISwimmingMammal>
returns a proxy24601
. Because they are completely different classes, the fact that IFlyingMammal
has different members from ISwimmingMammal
would pose no problem. The fact that the classes might have ugly machine-generated names wouldn't really matter because one wouldn't be declaring variables of type proxy8675309
or proxy24601
, but instead types IFlyingMammal
and ISwimmingMammal
.