A covariant generic interface preserves assignment compatibility: when Giraffe is assignable to Animal, IEnumerable<Giraffe> can be assigned to IEnumerable<Animal>. C# permits this only for certain interfaces and delegates, with a reference-type varying argument. section 2.3
Safety depends on direction of use. A covariant interface may produce values of T, but it must not accept T as an input. IEnumerable<T> is therefore eligible, while mutable IList<T> is not: treating IList<Tiger> as IList<Animal> would allow inserting a Giraffe into a tiger list. section 2.3
A covariant immutable stack
An immutable stack can declare interface IImStack<out T> : IEnumerable<T>, expose T Peek(), and return another IImStack<T> from Pop(). A stack of Tigers can then be viewed as a stack of Animals; pushing a Giraffe through the Animal view creates a new stack rather than mutating the original. section 2.3
In type theory, a generic interface acts like a function from types to types that preserves assignment-compatibility arrows. This makes it a covariant endofunctor when the source and target category are both the category of types. section 7.2 section 7.4
