A type parameter is in an output position when a value of that type is produced, returned, or exposed for reading. In C#, a generic interface may mark its parameter covariant with `out` only when every use has this shape. An `IEnumerable<T>` can therefore expose `T` while remaining safely covariant: an `IEnumerable<Giraffe>` can be assigned to an `IEnumerable<Animal>`. section 2.3 section 7.2
A read-only interface
An interface whose type parameter appears only in a getter can be declared covariant: `interface IE<out T> { T Current { get; } bool MoveNext(); }` The assignment `IE<Animal> animals = giraffes;` is then valid when `giraffes` has type `IE<Giraffe>`. The reverse direction is not implied: the interface produces animals, but it does not promise that every produced value is a giraffe. A method such as `Add(T value)` would put `T` in an input position and make covariance unsafe. section 7.2 section 2.3
This restriction explains a surprising immutable-stack design. `Peek()` returns `T`, but `Push(T)` consumes one. Moving `Push` into an extension method leaves the covariant interface with only output uses while preserving the call-site style. A stack of tigers can then be viewed as a stack of animals and extended with a giraffe, producing a new immutable stack rather than mutating the old one. section 2.3
Listing 2.5 A covariant immutable stack
interface IImStack<out T> : IEnumerable<T> #1
{
T Peek(); #2
IImStack <T> Pop();
bool IsEmpty { get; }
}
class ImStack<T> : IImStack<T>
{
…
public static IImStack<T> Push(T item, IImStack<T> tail) => #3
new ImStack<T>(item, tail);
…
}
static class Extensions #4
{
public static IImStack<T> Push<T>(this IImStack<T> stack, T item) =>
ImStack<T>.Push(item, stack);
}
IImStack<Tiger> s1 = ImStack<Tiger>.Empty;
IImStack<Tiger> s2 = s1.Push(new Tiger());
IImStack<Tiger> s3 = s2.Push(new Tiger());
IImStack<Animal> s4 = s3; #5
IImStack<Animal> s5 = s4.Push(new Giraffe());
Console.WriteLine(s5.Bracket());
Inspect the complete covariant immutable-stack implementation, including output-only interface members, the static Push operation, its extension-method form, and the Tiger-to-Animal assignment. section 2.3

