In my head, this should work.
The problem is in your head! :-) This should not work. Let's see why.
interface ICage { void Enclose(Animal animal); } class ZooCage<T> : ICage where T : Animal { public void Enclose(T t) { ... } } ... var giraffePaddock = new ZooCage<Giraffe>(); var cage = (ICage)giraffePaddock; var tiger = new Tiger(); icage.Enclose(tiger);
And now there's a tiger in the giraffe's pen, and life is good for a tiger, but bad for giraffes. That is why it is illegal.
Or does the compiler need EXACTLY the same implementation as the interface definition?
An element that implements an interface member must exactly match the signature of the implemented method. For example, you cannot use return type covariance:
interface I { Animal GetAnimal(); } class C : I { public Giraffe GetAnimal() { ... }
The contract requires an animal; you provide a giraffe. This should work, logically, but it is not legal in C #. (It is in C ++.)
Look at any of the many questions on this site about return type covariance for reasons.
Similarly for the contravariance of the parameter:
interface I { void PutMammal (Mammal mammal); } class C : I { public PutMammal(Animal animal) { ... }
Again, this is logically reasonable; the contract requires you to take a mammal, and that accepts any animal. But then again, this is not legal.
In C #, there are some covariant and contravariant operations; see any of the many questions on these topics on this site or browse covariance and contravariance articles on ericlippert.com or on my previous msdn blog.